gpt4 book ai didi

elixir - 大文件和散列 - 性能问题

转载 作者:行者123 更新时间:2023-12-02 04:48:30 25 4
gpt4 key购买 nike

我正在尝试使用以下代码逐行对文件 (16 MB) 进行哈希处理:

 def hash(data, protocol) do
:crypto.hash(protocol, data)
|> Base.encode16()
end

File.stream!(path)
|> Stream.map(&hash(&1, :md5) <> "h")
|> Enum.to_list()
|> hd()
|> IO.puts()

根据 time 命令,这需要 10 到 12 秒,这似乎是一个很大的数字,我考虑到以下 Python 代码:

import md5

with open('a', 'r') as f:
content = f.readlines()
l = []
for _, val in enumerate(content):
m = md5.new()
m.update(val)
l.append(m.hexdigest() + "h")

print l[0]

运行(仍然根据时间)大约需要2.3秒。

我应该从哪里开始提高 Elixir 代码的性能?我尝试将初始流分成 10 个 block ,并为每个 block 触发一个异步任务:

File.stream!(path)
|> Stream.chunk(chunk_size) # with chunk_size being (nb_of_lines_in_file / 10)
|> Enum.map(fn chunk -> Task.async(fn -> Enum.map(chunk, &hash(&1, :md5) <> "h") end) end)
|> Enum.flat_map(&Task.await/1)
|> hd()
|> IO.puts()

但它会产生甚至或更差的结果,运行时间大约为 11 秒以上,这是为什么?

最佳答案

需要考虑的一件事是,使用时间来记录 Elixir 代码的性能总是会考虑到BEAM 虚拟机的启动时间。取决于您的应用程序中,将其包含在任何应用程序中可能有意义也可能没有意义与其他语言的比较基准。如果你只是想最大化 Elixir 代码的性能,最好使用基准测试像 Benchfella 这样的工具,甚至只是来自 erlang 的 :timer.tc。

https://hex.pm/packages/benchfella

我的猜测是你的性能问题都与 I/O 相关。File.stream! 对于大文件的行处理并不是特别有效。

我写了一篇关于散列整个文件的类似问题的博客文章。

http://www.cursingthedarkness.com/2015/06/micro-benchmarking-in-elixir-using.html

这里有一个关于进行基于快速行的处理的幻灯片。

http://bbense.github.io/beatwc/

我认为如果您将整个文件放入其中,您将获得更好的性能。我会毫不犹豫地使用

File.stream!(path) |> Enum.map(fn(line) -> hash(line, :md5) <> "h" end )

对于 16mb 文件。在管道中使用 Stream 几乎总是以速度换取内存使用。由于数据在 Elixir 中是不可变的,因此大型列表的开销通常比您最初预期的要少。

您基于任务的代码不会有太大帮助,因为我怀疑大多数时间花在对这两行中的行进行分块上。

File.stream!(path)
|> Stream.chunk(chunk_size) # with chunk_size being (nb_of_lines_in_file / 10)

这会非常慢。您可能会发现有用的另一个代码示例。 https://github.com/dimroc/etl-language-comparison/tree/master/elixir

您可以使用很多技巧在 Elixir 中实现快速文件处理。您通常可以将简单的 File.stream! 版本的速度提高多个数量级。

关于elixir - 大文件和散列 - 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34355925/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com