Большой обмен бинарными данными между процессами

У меня есть большие бинарные данные iof ip data о Xmb. Процессы используют двоичный код, выполняют некоторый алгоритм поиска для поиска IP-адреса. У меня есть три метода. 1. поставить в етс. но я полагаю, что каждый доступ для чтения будет копировать большой двоичный файл для обработки. :( 2. поместить в состояние gen_server. процессы используют gen_server:call для получения адреса. Короткий параллелизм. 3. скомпилировать двоичный файл в луч. но когда я компилирую, получаю eheap_alloc: Cannot allocate 1318267840 bytes of memory (of type "heap")

какая лучшая практика обмена большими данными в erlang?


person 柚子youthy    schedule 01.12.2017    source источник
comment
извините за плохую верстку.   -  person 柚子youthy    schedule 01.12.2017


Ответы (1)


Двоичные файлы размером более 64 байт хранятся как двоичные файлы с подсчетом ссылок, а их данные хранятся вне кучи любого процесса. Если такой двоичный файл отправляется какому-либо процессу, базовые данные не дублируются. Таким образом, если вы сохраните такой двоичный файл в таблице ETS, а затем получите к нему доступ из различных процессов, базовые данные не будут скопированы, а будет увеличиваться/уменьшаться только его счетчик ссылок. Я бы предложил использовать табличное решение ETS.

Вот демонстрация использования памяти при загрузке, после вставки двоичного файла размером 100 МБ в таблицу ETS и после извлечения копии двоичного файла в процесс оболочки. Использование памяти не меняется после того, как у нас есть двоичная копия, сохраненная в процессе оболочки. То же самое было бы неверно, если бы мы копировали строку из миллиона символов (список целых чисел) из ETS или другого процесса.

1> erlang:memory().
[{total,21912472},
 {processes,5515456},
 {processes_used,5510816},
 {system,16397016},
 {atom,223561},
 {atom_used,219143},
 {binary,844872},
 {code,4808780},
 {ets,301232}]
2> ets:new(foo, [named_table, set]).
foo
3> ets:insert(foo, {foo, binary:copy(<<".">>, 104857600)}).
true
4> erlang:memory().
[{total,127038632},
 {processes,5600320},
 {processes_used,5599952},
 {system,121438312},
 {atom,223561},
 {atom_used,220445},
 {binary,105770576},
 {code,4908097},
 {ets,308416}]
5> X = ets:lookup(foo, foo).
[{foo,<<"........................................................................................................"...>>}]
6> erlang:memory().
[{total,127511632},
 {processes,6082360},
 {processes_used,6081992},
 {system,121429272},
 {atom,223561},
 {atom_used,220445},
 {binary,105761504},
 {code,4908097},
 {ets,308416}]

Вы можете найти гораздо больше информации о том, как эффективно работать с двоичными файлами в Erlang, по ссылке выше.

person Dogbert    schedule 01.12.2017
comment
какие процессы_используемые увеличились примерно на 482040 байт после поиска? Я предполагал, что это увеличит ту же память в ets после вставки, но ets увеличит только 7184 байта. - person 柚子youthy; 02.12.2017
comment
Значения продолжают незначительно колебаться, поскольку все всегда работает в фоновом режиме, как и сборщик мусора. Память ETS не увеличилась, поскольку двоичный файл хранится в двоичной куче. ETS хранит только ссылку на двоичный файл, как это делают процессы, когда у вас есть большой двоичный файл. - person Dogbert; 02.12.2017
comment
3кв за ответ - person 柚子youthy; 02.12.2017