Использование памяти массивами

Я разрабатываю синтаксический анализатор CSV, который должен иметь возможность обрабатывать огромные наборы данных (читать 10 миллионов строк) в браузере.

В основном парсер работает следующим образом:

  1. Основной поток читает кусок размером 20 МБ, иначе браузер быстро рухнет. После этого отправляет прочитанный кусок данных одному из воркеров.

  2. Рабочий получает данные и отбрасывает столбцы, которые мне не нужны, и сохраняет те, которые мне нужны. Обычно мне нужны только 4-5 столбцов из 20-30.

  3. Рабочий процесс отправляет обработанные данные обратно в основной поток.

  4. Основной поток получает данные и сохраняет их в массиве данных.

  5. Повторяйте шаги 1-4, пока файл не будет готов.

В конце с набором данных (преступления города chicago), я получаю массив, внутри которого находится 71 другой массив, и каждый из этих массивов содержит +/- 90 000 элементов. Каждый из этих 90К элементов содержит 5 строк (столбцов, взятых из прочитанного файла). А именно широта, долгота, год, блок и IUCR.

Подводя итог, 71 — это количество фрагментов по 20 МБ в наборе данных, 90 КБ — количество строк в каждом фрагменте по 20 МБ, а 5 — это извлеченные столбцы.

Я заметил, что браузер (Chrome) использует слишком много памяти, поэтому я попробовал в 4 разных браузерах (Chrome, Opera, Vivaldi и Firefox) и записал память, используемую вкладкой.

  1. Хром — 1,76 ГБ
  2. Опера - 1,76 ГБ
  3. Фаерфокс — 1,3 ГБ
  4. Вивальди - 1 ГБ

Если я попытаюсь воссоздать тот же массив, но с фиктивными данными, он использует только прибл. 350 МБ памяти.:

var data = [];
for(let i = 0; i < 71; i++){
    let rows = [];
    for(let j = 0; j < 90*1000; j++){
        rows.push(["029XX W MADISON ST", "2027", "-87.698850575", "2001", "41.880939487"])
    }
    data.push(rows);
}

Я понимаю, что если массив статический, как показано в приведенном выше коде, его легче выполнить лучше, чем динамический случай. Но я не ожидал использовать в 5 раз больше памяти для того же количества данных.

Что я могу сделать, чтобы использовать меньше памяти в синтаксическом анализаторе?


person Rui Alves    schedule 21.05.2017    source источник
comment
Я действительно не думаю, что вы должны пытаться сделать это в браузере.   -  person    schedule 21.05.2017
comment
Вы можете запустить это на сервере (возможно, nodejs), он не зависит от изменения среды/памяти и имеет хорошую реализацию, называемую потоком...   -  person Jonas Wilms    schedule 21.05.2017
comment
@torazaburo, наверное, ты прав. Можете ли вы назвать мне причины, почему я не должен этого делать?   -  person Rui Alves    schedule 21.05.2017
comment
@Jonasw проблема в том, что я разрабатываю клиентский API для создания тематических карт. Важно сделать это на стороне клиента. Но я знаю, что есть ограничения для клиентской стороны, и я хочу проверить эти ограничения, чтобы затем иметь возможность сказать, что после, скажем, 2 миллионов строк это не должно быть сделано только на стороне клиента.   -  person Rui Alves    schedule 21.05.2017
comment
Я бы сохранил его на стороне сервера, затем передал бы запросы и т. Д. На сервер и вернул бы небольшие фрагментированные результаты ... Однако я не могу сказать вам, почему потребление памяти такое высокое ...   -  person Jonas Wilms    schedule 21.05.2017
comment
память около 1,5 ГБ предназначена для всего процесса или только для шага 4?   -  person Pablo Cesar Cordova Morales    schedule 21.05.2017
comment
Кстати, ваши воркеры правильно утилизируют свою память? Может в этом проблема...   -  person Jonas Wilms    schedule 21.05.2017
comment
@PabloCesarCordovaMorales память ок. 1,5 ГБ в конце. Когда все сделано, и у меня есть данные, извлеченные из файла.   -  person Rui Alves    schedule 21.05.2017
comment
@ Джонас, я так думаю. См. описание worker.js. Основной поток даже посылает команду terminate() всем рабочим процессам, когда работа выполнена.   -  person Rui Alves    schedule 21.05.2017
comment
Вы говорите, что вы получаете 4-5 столбцов, и где ваши данные являются переменными для 4-5 столбцов, я знаю, что веб-движок v8 оптимален для объектов одного типа, возможно, вы можете заставить всегда иметь 5 столбцов, чтобы оптимизировать ваш процесс: youtube.com/watch?v=p-iiEDtpy6I&t=1241s   -  person Pablo Cesar Cordova Morales    schedule 21.05.2017
comment
@PabloCesarCordovaMorales я пытался создать объект с 5 полями, но не сильно улучшился. Это была твоя идея или я не понял?   -  person Rui Alves    schedule 21.05.2017
comment
Ваши результаты довольно странные, учитывая, что Vivaldi, Opera и Chrome используют один и тот же движок. Может разные версии? Или команда Vivaldi просто настроила параметры для уменьшения объема памяти.   -  person Bergi    schedule 23.05.2017
comment
Я предполагаю, что ваш статический массив занимает гораздо меньше памяти, потому что строки интернированы, поэтому все эти 639K строк ссылаются на одну и ту же память данных, в отличие от множества разных строк в ваших реальных данных.   -  person Bergi    schedule 23.05.2017
comment
@ Берги, ты прав. Я уже внес некоторые улучшения в свой код, и теперь он использует гораздо меньше памяти.   -  person Rui Alves    schedule 23.05.2017


Ответы (1)


В основном, чтобы использовать меньше памяти, можно использовать некоторые методы.

Во-первых, столбцы CSV, которые содержат числа, должны быть преобразованы и использованы как таковые. Поскольку числа в Javascript занимают 8 байтов, но то же число, что и строка, может занимать гораздо больше места (2 байта на символ).

Другое дело — уволить всех работников, когда работа будет выполнена.

person Rui Alves    schedule 28.05.2017