Elixir实用程序脚本的内存使用情况,该脚本可将内容从stdin过滤到sdout

时间:2019-02-22 21:48:26

标签: elixir

我正在尝试编写一个简单的elixir实用程序脚本,该脚本将一些文本作为来自STDIN(即PostgreSQL转储)的输入,过滤该文本并将其输出到STDOUT以供后续命令使用:

pg_restore db-backup/big_dump.psql.gz | db_trimmer.exs | psql ...

我的脚本的第一个版本是删除转储复制数据的所有行(以COPY开始,以\.结尾):

COPY xx_table ... FROM stdin
4       33380   \N      \N
4       33380   \N      \N
\.

我的目标是控制该脚本使用的内存,因为转储可能非常大。因此,我开始使用Elixir Stream模块和功能。我最后使用IO.streamStream.transform进行了第一个实现:

IO.stream(:stdio, :line)
|> Stream.transform(false, fn line, skipping ->
  cond do
    !skipping && String.starts_with?(line, "COPY") -> {[{true, line}], true}
    skipping && line == "\\.\n" -> {[{true, line}], false}
    true -> {[{skipping, line}], skipping}
  end
end)
|> Stream.filter(fn {skipping, _} -> !skipping end)
|> Stream.map(fn {_, line} -> line end)
|> Stream.into(IO.stream(:stdio, :line))
|> Stream.run()

但是,当我在一个大型转储上运行此脚本时,我注意到,首先进程内存开始大量增长,然后稳定下来。但是随后过程虚拟内存继续增长...

我注意到一个更简单的脚本具有相同的行为:

IO.stream(:stdio, :line)
|> Stream.into(IO.stream(:stdio, :line))
|> Stream.run()

我想知道如何控制该脚本的内存使用(缓冲区,内存中的行数)?您对如何更好地实现此逻辑有建议吗?也许我应该放弃使用STDIN和STDOUT的想法,并在Elixir中使用所有管道?

1 个答案:

答案 0 :(得分:0)

可以尝试Flow吗?您可以使用this trick在脚本文件中使用依赖项。