У меня проблема с Firebase при попытке загрузить ордера (20К узлов) с помощью события child_added. Потребление памяти увеличивается и никогда не уменьшается снова. Как только я остановлю скрипт nodejs, он вернется к нормальному состоянию.
Моя проблема в том, что я запускаю этот скрипт на сервере nodejs (при запуске), поэтому память на сервере увеличивается и больше никогда не падает.
попытался создать снимок кучи памяти после извлечения всех дочерних элементов узла "orders". Он показал, что большая часть выделения памяти происходит внутри объектов:
- LLRBNode => 30%
- (строка) => 34%
- LeafNode => 20%
, которые в основном являются членами объекта снимка Firebase "sOrder". Мой оригинальный код выполнялся без использования «global.gc», но я добавил, что для того, чтобы убедиться, что Garbage Collector работает и в обоих случаях возникает одна и та же проблема с памятью.
Я использую сценарий так:
node --expose-gc orders_load.js
Я не использую отладку для воспроизведения этого случая. Мой пример кода:
console.log( "starting... " );
try
{
let i = 1;
firebase.database().ref("orders").on( "child_added", ( sOrder ) =>
{
console.log( "** " + i++ );
if ( global.gc )
{
if( i % 1000 == 0 )
{
console.log( "running garbage collector" );
global.gc();
}
}
else
console.log( 'Garbage collection unavailable.' );
} );
}
catch( err )
{
console.log( `EXCEPTION-%s`, err.message );
}
мой узел "orders" имеет 20K записей, и когда я запускаю приведенный выше код, объем свободной памяти уменьшается с 2181 до 1426 Мб (755 Мб памяти). Любая идея, почему объект снимка всех моих заказов, кажется, сохраняется в памяти даже после завершения функции обратного вызова для события child_added?
firebase-admin: 6.4.0
nodejs: v11.6.0
===========================
После применения некоторых подсказок из Фрэнка ниже я получил следующий код:
let i = 1;
function child_added( sOrder )
{
console.log( "** " + i++ + " %s", sOrder.key );
}
console.log( "starting... " );
try
{
firebase.database().ref("orders").once( "value", ( sOrders ) =>
{
sOrders.forEach( child_added );
process.nextTick( () =>
{
firebase.database().ref("orders").limitToLast(1).on( "child_added", ( sOrder ) =>
{
child_added( sOrder );
} );
} );
} );
}
catch( err )
{
console.log( `EXCEPTION-%s`, err.message );
}
Это работает, и потребление памяти исчезло. Итак, я получаю все дочерние элементы узла "orders" + получаю новые заказы, приходящие + на память мало yay !!