#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 и перечитываете их снова