-
Notifications
You must be signed in to change notification settings - Fork 41
Description
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);