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

Allow parallel execution of node event loop and sqlite3 in Statement:Work_AfterAll

Open alex3d opened this issue 4 years ago • 2 comments

This PR allows the eager start of the next queued query execution in Statement::All - before the JS callback execution. In some cases, it could double performance by allowing parallel execution of node event loop and sqlite3 query processing in the thread pool.

Here is a microbenchmark with 1.7 performance improvement:

$ node perf.js # before PR 
elapsed 1488 ms,  1.488 ms per SELECT, event loop utilization=0.5520233139076274

$ node perf.js # after PR
elapsed  856 ms,  0.856 ms per SELECT, event loop utilization=0.9129801163162077
const sqlite3 = require('./lib/sqlite3');
const {promisify} = require('util');
const {performance} = require('perf_hooks');

async function main() {
  let db = new sqlite3.Database(':memory:');
  const prepare = (sql) => new Promise((resolve, reject) => {
    const stmt = db.prepare(sql, err => {
      if (err===null)
        resolve(stmt);
      else
        reject(err);
    });
  });
  
  await promisify(db.run).call(db, "CREATE TABLE lorem (info TEXT)");
  let insert = await prepare("INSERT INTO lorem VALUES (?)");
  for (var i = 0; i < 2000; i++) {
      await promisify(insert.run).call(insert, "Ipsum " + i);
  }

  let select = await prepare("SELECT max(id), max(info) FROM (SELECT rowid AS id, info FROM lorem) GROUP BY id%500;");
  let all = promisify(select.all.bind(select));
  const QUERIES = 1000;
  const T0 = Date.now(), ELU0=performance.eventLoopUtilization();
  
  await Promise.all(new Array(QUERIES).fill(0).map(() => all().then(v=>JSON.stringify(v)) ));
  
  const T1 = Date.now(), ELU1=performance.eventLoopUtilization(ELU0);
  console.log(`elapsed ${T1-T0} ms,  ${(T1-T0)/QUERIES} ms per SELECT, event loop utilization=${ELU1.utilization}`);
}

main().catch(console.error);

alex3d avatar Oct 19 '21 10:10 alex3d

Hey @alex3d! 👋🏻 Looks interesting! Would you be able to rebase the PR?

daniellockyer avatar Apr 13 '22 10:04 daniellockyer

@daniellockyer I've rebased PR and checked microbenchmark again - performance improvement stayed roughly the same

alex3d avatar Jun 07 '22 17:06 alex3d