Skip to content

Memory leak(?) in Version 1.0.24 #32

@viktor-ch

Description

@viktor-ch

It seems to be a memory leak in the latest version when calling .exec() within a promise.

I tested two last versions (1.0.23 and 1.0.24) with node 10.14.2 using the test code below. The standard callback approach works just fine in both versions. But when using promises I observed significant heap usage growth in version 1.0.24.

Thank you very much in advance,
Viktor

Test results:

v.1.0.23:
Callbacks:
Start : heapTotal = 6.23 MB, heapUsed = 3.73 MB
Finish: heapTotal = 40.23 MB, heapUsed = 9.94 MB
Promises:
Start : heapTotal = 6.23 MB, heapUsed = 3.73 MB
Finish: heapTotal = 43.23 MB, heapUsed = 19.33 MB

v.1.0.24:
Callbacks:
Start : heapTotal = 6.23 MB, heapUsed = 3.73 MB
Finish: heapTotal = 43.23 MB, heapUsed = 9.95 MB
Promises:
Start : heapTotal = 6.23 MB, heapUsed = 3.73 MB
Finish: heapTotal = 617.23 MB, heapUsed = 578.01 MB

Test :

const conn = require('sqlanywhere').createConnection();

const dbParams = {
    // Server  : 'xxxxx',
    UserId  : 'DBA',
    Password: 'sql',
  };
const select = "SELECT row_num, 'test long long string' || row_num as str FROM sa_rowgenerator( 1, 50000 );"

//----------------------------------------------------------------------
// execute the select 'count' times using the standard callback approach 
function testCallback(count) {
    const exec = function() {
        conn.exec(select, (err, result) => {
            if(err) {
                console.log(err);
            }
            else {
                console.log(`Iteration: ${count} Rows: ${result.length}`);
                if(--count > 0) {
                    setTimeout(exec, 0)
                }
                else {
                    conn.disconnect(err => logMemoryUsage(usedStart, process.memoryUsage()));
                }
            }
        })
    }
    conn.connect(dbParams, err => err ? console.log(err) :  exec());
 }

//----------------------------------------------------------------------
// execute the select 'count' times using Promises 
async function testPromise(count) {
    const connect = async function() {
        return new Promise( (resolve, reject) => {
            conn.connect(dbParams, err => err ? reject(err) : resolve());
        });
    }
    const disconnect = async function() {
        return new Promise( (resolve, reject) => {
            conn.disconnect(err => err ? reject(err) : resolve());
        });
    }
    const exec = async function() {
        return new Promise( (resolve, reject) => {
            conn.exec(select, (err, result) => err ? reject(err) : resolve(result));
        });
    }
    try {
        await connect();
        for(let i = count; i > 0; --i) {
            const result = await exec();
            console.log(`Iteration: ${i} Rows: ${result.length}`);
        }
        await disconnect();
        logMemoryUsage(usedStart, process.memoryUsage());
    }
    catch(err) {
        console.log(err);
    }
 }

//----------------------------------------------------------------------
const usedStart = process.memoryUsage();
function logMemoryUsage(startMemory, finishMemory) {
    const toMB = mem => Math.round(mem / 1024 / 1024 * 100) / 100; 
    console.log(`Start : heapTotal = ${toMB(startMemory.heapTotal) } MB, heapUsed = ${toMB(startMemory.heapUsed) } MB`);
    console.log(`Finish: heapTotal = ${toMB(finishMemory.heapTotal)} MB, heapUsed = ${toMB(finishMemory.heapUsed)} MB`);
}

//----------------------------------------------------------------------
// enable one of the following functions:
//----------------------------------------------------------------------
// testCallback(100);
testPromise(100);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions