Процесс эликсира занимает слишком много памяти - PullRequest
0 голосов
/ 09 января 2019

Я читаю почтовые индексы из CSV-файла, беру эти данные и кеширую их с помощью ets.

Файл почтового индекса довольно большой (95 МБ), поскольку в нем содержится около 1,8 миллиона записей.

Я кеширую только те почтовые индексы, которые необходимы для поиска в данный момент (около 200 КБ), поэтому объем данных, хранящихся в ets, не должен быть проблемой. Однако независимо от того, насколько мало количество вставок в ets, объем памяти, занимаемый процессом, практически не изменяется. Кажется, не имеет значения, если я вставлю 1 строку или все 1,8 млн.

# 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 становится большой (более 600 МБ)

Даже если я отфильтрую файл, чтобы в итоге я сохранил только один почтовый индекс в :ets, он все равно будет превышать 600 МБ.

1 Ответ

0 голосов
/ 09 января 2019

Я понял, что ошибка, которую я делал, была, когда я смотрел на память процесса и предполагал, что это было связано с кешем.

Поскольку это GenServer, он сохраняет всю информацию из CSV-файла при его чтении (File.read!), А также, похоже, также сохраняет все изменения, внесенные в этот файл.

Как я решил это, изменив 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

При таком подходе память моего процесса теперь составляет всего около 2 МБ (не 632 МБ), а память ets составляет около 30 МБ. Это то, что я ожидал.

...