Erlang进程信息中存在重复的二进制文件
我试图通过对Erlang进程信息中存在重复的二进制文件,erlang,elixir,Erlang,Elixir,我试图通过对process.info(pid,:binary)的结果求和来计算一个进程保留了多少二进制内存,但它给出了不准确的结果。在一台有128GB内存的机器上,它说一个进程使用了超过1TB的内存 我想我已经把问题归结到多次返回包含相同二进制文件的列表的Process.info 这是一个长生不老药脚本,演示了我所看到的。“垃圾文件”是我创建的一个文件,它有一堆JSON对象,每行一个对象 result = Stream.iterate(0, & &1 + 1) |>
process.info(pid,:binary)
的结果求和来计算一个进程保留了多少二进制内存,但它给出了不准确的结果。在一台有128GB内存的机器上,它说一个进程使用了超过1TB的内存
我想我已经把问题归结到多次返回包含相同二进制文件的列表的Process.info
这是一个长生不老药脚本,演示了我所看到的。“垃圾文件”是我创建的一个文件,它有一堆JSON对象,每行一个对象
result =
Stream.iterate(0, & &1 + 1)
|> Stream.take(10_000)
|> Flow.from_enumerable(max_demand: 1)
|> Flow.flat_map(fn _ ->
File.read!("junk_file") |> String.split("\n")
end)
|> Enum.to_list()
system_binary_bytes =
:erlang.memory() |> Keyword.get(:binary)
{:binary, binaries} =
Process.info(self(), :binary)
binary_ids =
Enum.map(binaries, &elem(&1, 0))
binary_bytes =
Enum.map(binaries, &elem(&1, 1))
|> Enum.sum()
unique_binary_bytes =
Enum.uniq_by(binaries, fn {id, _, _} -> id end)
|> Enum.map(&elem(&1, 1))
|> Enum.sum()
unique_ids =
MapSet.new(binary_ids)
unique_ids_times_ref =
Enum.uniq_by(binaries, fn {id, _, _} -> id end)
|> Enum.map(& elem(&1, 2))
|> Enum.sum()
IO.puts("binary_ids #{Enum.count(binary_ids)}")
IO.puts("unique_ids #{Enum.count(unique_ids)}")
IO.puts("binary_bytes #{binary_bytes}")
IO.puts("unique_bytes #{unique_binary_bytes}")
IO.puts("unique_ids_times_ref #{unique_ids_times_ref}")
IO.puts("system_binary_bytes #{system_binary_bytes}")
Enum.count(result)
以下是示例运行的结果:
binary_ids 2166004
unique_ids 10003
binary_bytes 373817119944
unique_bytes 1725843360
unique_ids_times_ref 2166009
system_binary_bytes 1731508128
正如您所看到的,有相当多的id是重复的,在按二进制id进行重复数据消除后,对每个二进制文件的报告内存求和会使总数更接近系统总数
假设二进制ID是唯一的,并且可以用于删除列表中的重复数据,这样安全吗?这是解决我的问题的正确方法吗?旁注:你在滥用管道操作员Enum.map(binaries,&elem(&1,1))|>Enum.sum()
应在此处和任何地方写成binaries |>Enum.map(&elem(&1,1))|>Enum.sum()
。