Как исправить Node.js ошибка нехватки памяти в куче?

#node.js #mongodb #memory #memory-leaks

#node.js #mongodb #память #утечки памяти

Вопрос:

Я хочу прочитать содержимое файлов JSON, расположенных на диске, и вставить их содержимое в таблицу базы данных MongoDB. Вот код:

 const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;

const fs = require('fs');
const dataFolder = './json-data';

const connectionURL = 'mongodb://127.0.0.1:27017';
const databaseName = 'database';

MongoClient.connect(connectionURL, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}, (error, client) => {
    if (error) {
        return console.log('Unable to connect to database!');
    }

    const db = client.db(databaseName);
    fs.readdir(dataFolder, (err, files) => {
        files.forEach(file => {
            insertCollection(file);
        });
    });

    function insertCollection(file) {
        fs.readFile(`${dataFolder}\${file}`, "utf8", (err, res) => {

            db.collection('barcode').insertMany(JSON.parse(res), (err, res) => {
                if (err) {
                    return console.log('Unable to insert barcode!');
                }

                console.log(typeof res.ops);
            });
        })
    }
});
 

Немного позже Node.js умирает с:

 <--- Last few GCs --->

[3144:00000258BE35C750]    24799 ms: Mark-sweep (reduce) 2046.7 (2056.6) -> 2046.5 (2058.4) MB, 704.2 / 0.0 ms  (  0.0 ms in 15 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 706 ms) (average mu = 0.121, current mu = 0.[3144:00000258BE35C750]    25503 ms: Mark-sweep (reduce) 2047.5 (2054.4) -> 2047.4 (2055.1) MB, 700.5 / 0.0 ms  (  0.0 ms in 2 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 702 ms) (average mu = 0.066, current mu = 0.0

<--- JS stacktrace --->

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
 1: 00007FF65D28021F napi_wrap 109311
 2: 00007FF65D225286 v8::internal::OrderedHashTable<v8::internal::OrderedHashSet,1>::NumberOfElementsOffset 33302
 3: 00007FF65D226056 node::OnFatalError 294
 4: 00007FF65DAF054E v8::Isolate::ReportExternalAllocationLimitReached 94
 5: 00007FF65DAD53CD v8::SharedArrayBuffer::Externalize 781
 6: 00007FF65D97F85C v8::internal::Heap::EphemeronKeyWriteBarrierFromCode 1516
 7: 00007FF65D96A49B v8::internal::NativeContextInferrer::Infer 59243
 8: 00007FF65D94F9CF v8::internal::MarkingWorklists::SwitchToContextSlow 57327
 9: 00007FF65D96361B v8::internal::NativeContextInferrer::Infer 30955
10: 00007FF65D95A73D v8::internal::MarkCompactCollector::EnsureSweepingCompleted 6269
11: 00007FF65D96286E v8::internal::NativeContextInferrer::Infer 27454
12: 00007FF65D9667FB v8::internal::NativeContextInferrer::Infer 43723
13: 00007FF65D970052 v8::internal::ItemParallelJob::Task::RunInternal 18
14: 00007FF65D96FFE1 v8::internal::ItemParallelJob::Run 641
15: 00007FF65D9438E3 v8::internal::MarkingWorklists::SwitchToContextSlow 7939
16: 00007FF65D95ABEC v8::internal::MarkCompactCollector::EnsureSweepingCompleted 7468
17: 00007FF65D959434 v8::internal::MarkCompactCollector::EnsureSweepingCompleted 1396
18: 00007FF65D956F98 v8::internal::MarkingWorklists::SwitchToContextSlow 87480
19: 00007FF65D9855E1 v8::internal::Heap::LeftTrimFixedArray 929
20: 00007FF65D9876C5 v8::internal::Heap::PageFlagsAreConsistent 789
21: 00007FF65D97C971 v8::internal::Heap::CollectGarbage 2033
22: 00007FF65D97AB75 v8::internal::Heap::AllocateExternalBackingStore 1317
23: 00007FF65D99AF67 v8::internal::Factory::NewFillerObject 183
24: 00007FF65D6CAE7F v8::internal::interpreter::JumpTableTargetOffsets::iterator::operator= 1039
25: 00007FF65DB78EFD v8::internal::SetupIsolateDelegate::SetupHeap 463949
26: 0000001C8935F3C0
 

Я пробовал memwatch, но с момента последнего коммита прошло уже около 9 лет, а я даже не смог его установить. Как можно устранить подобную утечку?

Комментарии:

1. насколько велика папка? сначала вы загружаете память всей папкой, а затем для каждого файла повторно инициируете чтение файла, не могли бы вы вместо загрузки всей папки использовать другой подход — загружать только файлы по отдельности

2. @Mayur можете ли вы указать, где именно происходит повторная инициализация чтения файла?

3. В папке @Mayur 700 файлов по 2 МБ каждый.

4. о, извините, я думал, что вы читаете все файлы в функции readdir и перечитываете их снова