我正在从一个csv文件中读取邮政编码,获取该数据并用ets进行缓存。
邮政编码文件很大(95MB),因为其中包含约180万个条目。
我现在仅缓存查找所需的邮政编码(大约200k),因此存储在ets中的数据量应该不是问题。但是,无论插入ets的数量有多小,该进程占用的内存量实际上都是不变的。我插入1行还是全部插入180万行似乎都没关系。
# not logging all functions defs so it is not too long.
# Comment if more into is needed.
defmodule PostcodeCache do
use GenServer
def cache_postcodes do
"path_to_postcode.csv"
|> File.read!()
|> function_to_parse()
|> function_to_filter()
|> function_to_format()
|> Enum.map(&(:ets.insert_new(:cache, &1)))
end
end
我正在iex -S mix
在终端中运行此命令,并运行命令:observer.start
。当进入“进程”选项卡时,我的postcodeCache内存很大(超过600MB)
即使我过滤了文件,所以最终只能在:ets
中存储1个邮政编码,但仍然超过600MB。
答案 0 :(得分:6)
我意识到我犯的错误是当我查看进程的内存并假设它与缓存有关时。
因为这是GenServer,所以它在读取csv文件(File.read!)时会保留所有csv文件中的信息,并且似乎还保留对该文件所做的所有更改。
我如何解决此问题的方法是将File.read!
更改为File.stream!
。然后,我使用Enum.each
而不是映射返回的数据。
在每一个中,我检查邮政编码是我想要的,如果是,则将其插入ets。
def cache_postcodes do
"path_to_postcode.csv"
|> File.stream!()
|> Enum.each(fn(line) ->
value_to_store = some_check_on_line(line)
:ets.insert_new(:cache, &1)
end)
end
使用这种方法,我的进程内存现在只有大约2MB(而不是632MB),而ets的内存大约是30MB。那就是我所期望的。