Enum.filter 不可扩展?

bor*_*yer 1 scalability elixir

我解码 CSV 文件(使用https://hexdocs.pm/csv/),生成一个流,然后使用Enum.filter. 我的问题是处理时间并不随着 CSV 文件的大小线性增长:

% wc -l long.csv 
10000 long.csv
% time mix run testcvs.exs long.csv  
mix run testcvs.exs long.csv  3.08s user 0.50s system 242% cpu 1.479 total

% wc -l verylong.csv
100000 verylong.csv
% time mix run testcvs.exs verylong.csv 
mix run testcvs.exs verylong.csv  98.08s user 3.24s system 117% cpu 1:25.93 total
Run Code Online (Sandbox Code Playgroud)

应该需要十倍的时间,但实际上需要五十七倍的时间。绝对不可扩展。这是否意味着Enum.filter不使用流式传输而是将所有内容加载到内存中?是否有更可扩展的方法来过滤流?

代码:

Enum.at(System.argv(), 0)
|> File.stream!([:read], :line)
|> CSV.decode([separator: ?;])
|> Enum.filter(fn {:ok, line} -> Enum.at(line, 11) == "" end)
Run Code Online (Sandbox Code Playgroud)

Ada*_*hip 5

这是否意味着 Enum.filter 不使用流式传输而是将所有内容加载到内存中?

是的。正如丹尼尔在评论中提到的,对于流,您应该使用Stream.filter/2.

来自枚举的文档:

请注意,模块中的函数Enum是急切的:它们一旦被调用就会遍历可枚举对象。当使用无限可枚举时,这尤其危险。在这种情况下,您应该使用该Stream模块,它允许您延迟表达计算,而无需遍历集合,并可以处理可能无限的集合。请参阅该Stream模块以获取示例和文档。