NodeJS исчерпывает пространство кучи, когда я читаю большие файлы JSON в цикле - PullRequest
0 голосов
/ 10 мая 2018

У меня есть около 220 файлов JSON, каждый размером около 6 МБ, которые мне нужно проанализировать и обработать. Итак, я делаю это в цикле. Вот как я читаю и обрабатываю это:

        let fileList = fs.readdirSync('/500gb/json_files/gnip_30_p2');
        fileList = fileList.reverse();
        let totalErrors = 0;
        let totalFiles = 0;
        for (let file of fileList) { // TOTAL 220 FILES
            // READ EACH JSON FILE OF ~6MB
            let records = require(`/500gb/json_files/gnip_30_p2/${file}`);
            let results = records.results;
            if (results) {
                for (let record of results) {
                    // .. Some Processing Work Here ..
                }
            }
        }

Теперь проблема в том, что после запуска в течение примерно 3 минут я получаю JavaScript heap out of memory ошибку:

[3661:0x28af890]    50503 ms: Mark-sweep 1310.9 (1467.4) -> 1310.7 (1470.9) MB, 612.9 / 0.0 ms  allocation failure GC in old space requested
[3661:0x28af890]    51132 ms: Mark-sweep 1310.7 (1470.9) -> 1310.7 (1434.4) MB, 627.7 / 0.0 ms  last resort GC in old space requested
[3661:0x28af890]    51759 ms: Mark-sweep 1310.7 (1434.4) -> 1310.7 (1429.4) MB, 626.4 / 0.0 ms  last resort GC in old space requested

Нет рекурсивного вызова, только зацикливание, чтение и последующая отправка прочитанных данных после некоторых изменений в службу, которая быстро реагирует. Что может быть причиной того, что NodeJS исчерпал пространство кучи? Разве это не правильный способ чтения больших файлов JSON и их обработки?

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

Как уже упоминалось в другом месте, вы загружаете все в память.

@ everett1992 предложение хорошее, но вы должны выяснить, почему.

Использование «потоков» только сохраняет »куски файла в памяти.С помощью потоков вы можете направить результаты в другие функции ...

Посмотрите цитируемые термины, есть много хороших статей.

0 голосов
/ 30 мая 2018

Попробуйте либо

  • Только чтение файла непосредственно перед обработкой данных и освобождение его после слов. Например, замените require(filepath); на JSON.parse(fs.ReadFileSync(filepath, 'utf8'));

  • Подготовка файлов заранее. например. разрезать файл на более мелкие куски


Это не ограничивается require.

HTTP-запросов и fs.ReadFile() будут выбрасывать Javascript heap out of memory для больших файлов. (Изображения, JSON и т. Д.)

Похожие: --max-old-space-size=xxxx не решает эту проблему. Существует различие между памятью для процессов и памятью для буферов. см. Этот выпуск .

~ Лично я никогда не решал это, чтобы с комфортом обеспечить лучшее решение, кроме подготовки ваших файлов перед их чтением.

Обновление: посмотрите JSONStream для большого файла JSON

0 голосов
/ 10 мая 2018

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

Вместо этого используйте fs.readFile.

...