Утечка памяти в Firebase с Nodejs - PullRequest
0 голосов
/ 20 января 2019

У меня проблема с 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 !!

1 Ответ

0 голосов
/ 20 января 2019

Когда вы присоединяете слушателя on, слушатель остается активным, пока вы не удалите его с помощью off.Пока слушатель активен, Firebase будет хранить в памяти копию всех данных, которые слушатель получает.Использование памяти в этой копии / кэше в памяти может быть весьма значительным, поэтому вы должны удалить своих слушателей, когда вам больше не нужны данные.

Чтобы удалить всех слушателей по ссылке:

firebase.database().ref("orders").off();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...