当尝试使用“ child_added”事件加载订单(2万个节点)时,Firebase出现问题。内存消耗增加,再也不会下降。一旦我停止了nodejs脚本,它就会恢复正常。
我的问题是(在启动时)我正在nodejs服务器上运行此脚本,因此,服务器上的内存增加了,再也没有减少了。
试图在检索“ orders”节点的所有子级之后生成内存的堆快照。它表明大多数内存分配都发生在对象内部:
基本上是“ sOrder” Firebase快照对象的成员。我的原始代码未使用“ global.gc”运行,但我添加了代码以确保垃圾收集器正在运行,并且在两种情况下,都发生了相同的内存问题。
我使用这样的脚本:
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 );
}
我的“订单”节点有20K条记录,一旦我运行了上面的代码,可用内存就从2181 Mb下降到1426 Mb(755 Mb内存)。知道为什么即使对“ child_added”事件的回调函数完成后,我所有订单的快照对象似乎仍保留在内存中吗?
firebase-admin:6.4.0 nodejs:v11.6.0
=========================== 在应用了以下 Frank 的提示后,我得到了以下代码:
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 );
}
这有效,并且内存消耗消失了。因此,我收到了“订单”节点的所有子级+收到新的订单+内存不足!
答案 0 :(得分:1)
当您附加on
侦听器时,该侦听器将保持活动状态,直到您使用off
将其删除为止。在侦听器处于活动状态时,Firebase会保留该侦听器收到的所有数据的内存中副本。此内存中副本/缓存的内存使用可能非常重要,因此,当您不再需要数据时,应该删除监听器。
要删除参考上的所有侦听器,请执行以下操作:
firebase.database().ref("orders").off();