node-oracledb icon indicating copy to clipboard operation
node-oracledb copied to clipboard

Memory leak in deqMany

Open boriborm opened this issue 2 years ago • 17 comments

  1. What versions are you using?

Platform: linux Node version: v14.17.6 Architecture: x64 node-oracledb version: 5.5.0 Oracle client version: 21.3.0.0.0

  1. Is it an error or a hang or a crash?

Crash

  1. What error(s) or behavior you are seeing?

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory

  1. Include a runnable Node.js script that shows the problem.
const oracledb = require('oracledb');
const conf = require('./config.json');
async function runQueue () {
  const pool = await oracledb.createPool(conf); // in conf connectString, user, password, events=true
  const conn = await pool.getConnection();
  const queue = await conn.getQueue('XXI.CLIENT_OUT');
  queue.deqOptions.visibility = oracledb.AQ_VISIBILITY_ON_COMMIT;
  queue.deqOptions.wait = 0;

  let c = 0;
  console.log(`start`);
  while (c<2000){
    await queue.deqMany(1000);  //queue hasn't messages, return undefined. More maxMessages value -> larger RSS leak
    const stats = process.memoryUsage ();
    console.log ( `count: ${c}, rss: ${stats.rss} `) ;
    c++;
  }
  console.log(`end`);
  await conn.close();
  await pool.close(1);
}
runQueue().catch(err=>console.log(err));

output:

start
count: 0, rss: 71262208 
count: 1, rss: 71585792 
count: 2, rss: 71585792 
count: 3, rss: 71852032 
...
...
count: 1989, rss: 203001856 
count: 1990, rss: 203001856 
count: 1991, rss: 203272192 
count: 1992, rss: 203542528 
count: 1993, rss: 203812864 
count: 1994, rss: 204083200 
count: 1995, rss: 204083200 
count: 1996, rss: 204083200 
count: 1997, rss: 204083200 
count: 1998, rss: 204083200 
count: 1999, rss: 204083200 
end

boriborm avatar Oct 05 '22 20:10 boriborm

Can you add code to create the queue and add runnable code do the enqueues, so we know what's in the queue?

cjbj avatar Oct 05 '22 20:10 cjbj

Queue is empty.

BEGIN 
  DBMS_AQADM.CREATE_QUEUE_TABLE(queue_table => 'MSG_QT',queue_payload_type => 'RAW'); 
  DBMS_AQADM.CREATE_QUEUE(queue_table => 'MSG_QT', queue_name => 'CLIENT_OUT);
  DBMS_AQADM.START_QUEUE('CLIENT_OUT); 
END

boriborm avatar Oct 05 '22 20:10 boriborm

@pvenkatraman another task for you :)

cjbj avatar Oct 05 '22 21:10 cjbj

Maybe bug in function dpiQueue_deqMany

When it run, then numMsgProps changed to 0 (no new messages, queue is empty)

I run code below and no memory leaks

static bool njsAqQueue_deqManyAsync(njsBaton *baton)
{
    njsAqQueue *queue = (njsAqQueue*) baton->callingInstance;

    baton->msgProps = calloc(baton->numMsgProps, sizeof(dpiMsgProps*));

    if (!baton->msgProps)
        return njsBaton_setError(baton, errInsufficientMemory);
/*
    if (dpiQueue_deqMany(queue->handle, &baton->numMsgProps,
            baton->msgProps) < 0)
        return njsBaton_setErrorDPI(baton);
*/
    baton->numMsgProps = 0; // Empty queue imitation
    return true;
}

Script in my first post output:

start
count: 0, rss: 60858368 
count: 1, rss: 61128704 
count: 2, rss: 61394944 
count: 3, rss: 61394944 
count: 4, rss: 61394944 
count: 5, rss: 61394944 
count: 6, rss: 61394944 
count: 7, rss: 61394944 
...
...
count: 1994, rss: 61669376 
count: 1995, rss: 61669376 
count: 1996, rss: 61669376 
count: 1997, rss: 61669376 
count: 1998, rss: 61669376 
count: 1999, rss: 61669376 
end

memory usage between 60858368 and 62414848

boriborm avatar Oct 06 '22 08:10 boriborm

Thanks @boriborm will take a look.

pvenkatraman avatar Oct 06 '22 08:10 pvenkatraman

Bug in dpiQueue__deq when numMsgProps > 1 and payload is 'RAW', then run this function

status = dpiOci__aqDeqArray(queue->conn, queue->name,
                queue->deqOptions->handle, numProps, queue->buffer.handles,
                payloadTDO, queue->buffer.instances, queue->buffer.indicators,
                queue->buffer.msgIds, error);

This function run OCI function OCIAQDeqArray :(

When i change it to

   /*
        status = dpiOci__aqDeqArray(queue->conn, queue->name,
                queue->deqOptions->handle, numProps, queue->buffer.handles,
                payloadTDO, queue->buffer.instances, queue->buffer.indicators,
                queue->buffer.msgIds, error);
  */
  status = 0;
  *numProps = 0; // Empty queue imitation

no memory leak

boriborm avatar Oct 06 '22 09:10 boriborm

Thanks, working with another team member on this issue. Will update soon.

pvenkatraman avatar Oct 13 '22 14:10 pvenkatraman

Is this problem solved in any specific version? Version less than 6 from here

JoshuaCEnrico avatar Sep 18 '23 08:09 JoshuaCEnrico

@JoshuaCEnrico The memory profile with node-oracledb 6.x has changed slightly, because of the refactoring to use less C code in general, in addition to the newly introduced Thin mode. We will try to see if this can be reproduced in the 6.x version and get back to you.

sharadraju avatar Sep 19 '23 10:09 sharadraju

@sharadraju The issue still exist, even in the v6.5.1

999max avatar Jun 04 '24 15:06 999max

@999max There were some memory leak issues with AQ which were fixed in the latest Oracle Instant Client libraries. Can you please try your test case with the latest Oracle Instant Client libraries: https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html

sharadraju avatar Aug 07 '24 13:08 sharadraju

hey @sharadraju
I tested with v6.6.0 but unfortunately the issue with memory leak in deqMany was NOT fixed

999max avatar Aug 09 '24 07:08 999max

@999max Can you please indicate what Oracle Instant Client library version was used. You will have to use the latest Oracle Instant Client libraries, preferably Oracle Instant Client 23.5. I am assuming the client platform is Linux.

sharadraju avatar Aug 09 '24 07:08 sharadraju

preferably Oracle Instant Client 23.5

Hi @sharadraju . Is this an official recommendation? Our DBA suggests taking a conservative approach and using 19 client for 19 database etc.

sosoba avatar Aug 14 '24 06:08 sosoba

The issue we think it was was fixed in 23.5. I don't see a backport for 19 having landed yet, but it was requested. The Oracle bug is 36741214

cjbj avatar Aug 14 '24 08:08 cjbj

@sharadraju Sorry, I didn't understand your question reagrding the 'Oracle Instant Client'. I guess I don't use the 'Oracle Instant Client'. I'm using only the 'node-oracledb' package inside my NestJs app for queue reading (deqMany, deqOne). And, as mentioned above, there is a memory leak in deqMany() only.

999max avatar Aug 18 '24 14:08 999max

@999max , Проблема не в node-oracledb. Проблема в oracle instant client, который использует node-oracledb. В 6-й версии, насколько я помню, работа с очередями средствами node-oracledb напрямую с сервером ещё не поддерживается и работает только через использование оракл клиент. А ошибка в нем. И соответствующий запрос уже в оракл сделан. Но там эту проблему вероятно решили в версии оракл клиента 23.5. Я дальше 21-й версии не проверял, т.к. реализовал код используя deqOne.

boriborm avatar Aug 18 '24 18:08 boriborm