更新了 Logger.metadata1 的文档 #5158
lexmeg :第一段要很简洁,因为它要起到概括作用啊。我们这样写好不好:"Alters the current process metadata according the given keyword list."?大家觉得咋样?
jeregrine :嗯?好像不是很规范啊。。。我觉得多分几段更好。
lexmag :我们可以在第二段解释它的工作原理:
Alters the current process metadata according the given keyword list.
<describes what happens in case of `nil` value under a key>
whatyouhide :我看行:)
最终结果:
@doc """
Adds the given keyword list to the current process metadata. This also allows you to
remove a key from the metadata by setting a key to nil.
"""
def metadata(keywords) do
{enabled?, metadata} = __metadata__()
metadata =
Enum.reduce(keywords, metadata, fn
{key, nil}, acc -> Keyword.delete(acc, key)
{key, val}, acc -> Keyword.put(acc, key, val)
end)
Process.put(@metadata, {enabled?, metadata})
:ok
end
让 File.write
和 File.write!
利用 writev
#5154
nathanl :为了优化性能,通常我们都会在:raw
模式下使用:file.write/3
,而不是:file.write_file/3
。这样子BEAM就会使用系统调用writev而不是write。
好处就是,写iolist的时候,BEAM就不需要把元素连接起来,并生成一个用来写入的binary了。操作系统会从内存中单独地读取每个元素;最后的输出只会产生在目标文件里。跳过连接成binary的步骤,减少了工作量,节约了时间,还减少了垃圾的产生。
注意:给定了一种字符编码,:raw模式就不能用了哦。在:raw模式下,BEAM不会再创建一个单独的进程来处理文件,我觉得它用的进程就是用来执行字符编码的那个。所以啊,如果给定了编码,比如UTF-8,那我们就不用:raw模式了,也就是说不使用writev。
fishcakez :我不是很懂啊,:raw模式下使用:file.write/3有什么不同?
注意在:file中有一处注释说:file.write_file/3应该被移动到文件服务器中以提高效率。正如:file.write_file/2使用raw模式,相当于在文件服务器中运行。
nathanl :好问题。我也觉着不应该有不同,但就是有嘛。当我在iex中这样:
:file.write_file("/tmp/tmp.txt", ["foo", "bar"], [:raw])
然后用Evan Miller的 dtrace 脚本来查看它,我发现用的是write。但是如果:
{:ok, file} = :file.open("/tmp/tmp.txt", [:write, :raw])
:file.write(file, ["foo", "bar"])
,,,这里用的就是writev了,说实话我也不造为啥。
josevalim :write_file 会先把所有东西都转换成binary。也就是说,如果给定了编码,我们就要把所有东西转换成binary了。(我们没用:raw模式)。
fishcakez :哥们儿这是个 :file 里的 bug 啊,如果是raw文件就不该调用 make_binary/1。
josevalim :差不多就是这个原因。我们要不要去Erlang/OTP里修复这个bug?
nathanl :因为Erlang的UTF-8编码靠不住么?我添加了一个对charlists转换的测试,发现如果给定一个很大的代码点,例如9731 (☃),Erlang就会发出抱怨。
fishcakez :我说,无论咱在这里做什么,都应该去把Erlang/OTP给修复了。
josevalim :好的,那样我们这里的问题也会被修复。
fishcakez :听起来不错哦。
nathanl :那太好了。如果我们准备好合并这个,我会保证是一次提交,这样当Erlang那边修复好了,我们可以很容易地移除。
josevalim :write_file期望的是IO数据。所以不会进行Unicode转换。我觉得任何>255的列表都会失败。我们之所以要转换成binary,是因为不使用raw模式的时候,会生成一个新的进程,用binary在进程间传输效率更高。调用IO.iodata_to_binary可以完成这个转换。
nathanl :基于fishcakez的反馈,不再自动设置为:raw模式。所以现在仅当用户使用File.write("/tmp/tmp.txt", [foo, bar, foo], [:raw])
的时候,能够得到writev的好处。
nathanl :所有问题都解决好之后,我会精简代码,然后提交。就像之前说的那样。
josevalim :nathanl,鉴于我们已经基本实现了file:write_file,我确信我们应该直接把修复发给Erlang/OTP。我之前之所以同意你的补丁,是因为我们默认是raw模式,但是fishcakez证明了这是个坏主意。
也就是说,我不认为我们应该合并这个修改,抱歉哥们儿。往好的地方想,如果没有你的补丁和工作,我们又怎么能得出这个结论呢,所以这些工作绝对没有白费。如果在为Erlang/OTP提交补丁的时候你需要帮助,或者你希望我来做这个,尽管说。
多谢了!
nathanl :没事儿!我想我会试试看的,但我会回来求助,毕竟哥从来没写过Erlang。
你看下我的理解正确不:它们在这一行里将输入转换成binary,应当把它改成仅在模式列表中没有raw时执行。
josevalim :是滴!
随时联系我。这个Pull request就先关了哈。