// package.json
{
"name": "stress-sqlite",
"scripts": {
"start": "node test.js"
},
"dependencies": {
"better-sqlite3": "^9.2.2",
"tmp": "^0.2.1"
}
}
// test.js
const { Worker, workerData} = require('node:worker_threads');
const { cpus } = require('os');
const Database = require("better-sqlite3");
const CPU_COUNT = cpus().length;
const CONCURRENCY_LEVEL = CPU_COUNT;
const DATABASE_FILES = 4;
const TOTAL_RECORDS = 500000;
const tmp = require("tmp");
tmp.setGracefulCleanup();
const tmpDir = tmp.dirSync({
prefix: 'stress-sqlite'
}).name;
async function run() {
prepareDatabases();
const dbFiles = dbFilesLoopingIterator();
console.time("Insertions")
const recordsPerWorker = Math.ceil(TOTAL_RECORDS / CONCURRENCY_LEVEL);
const workers = [];
for (let workerNo = 0; workerNo < CONCURRENCY_LEVEL; workerNo++) {
const dbFile = dbFiles.next().value;
const worker = runWorker(workerNo, recordsPerWorker, dbFile);
workers.push(worker);
}
await Promise.all(workers);
console.timeEnd("Insertions")
}
function prepareDatabases() {
const dbFiles = dbFilesLoopingIterator();
for (let i = 0; i < DATABASE_FILES; i++) {
const dbFile = dbFiles.next().value;
const db = new Database(dbFile);
db.exec("PRAGMA journal_mode = WAL;");
db.exec("CREATE TABLE IF NOT EXISTS data (info TEXT)")
}
}
function* dbFilesLoopingIterator() {
let current = 0;
while (true) {
yield tmpDir + '/' + current + '_database.db'
current = (current + 1) % DATABASE_FILES;
}
}
function runWorker(workerNo, numberOfWrites, dbFile) {
return new Promise((resolve, reject) => {
const worker = new Worker('./worker.js', {
workerData: { workerNo, numberOfWrites, dbFile }
});
worker.on('exit', resolve);
worker.on('error', reject);
});
}
run().catch(err => console.error(err));
// worker.js
const { workerData } = require('worker_threads');
const Database = require("better-sqlite3");
const db = new Database(workerData.dbFile)
db.exec('pragma busy_timeout = 10000;');
db.exec("PRAGMA journal_mode = WAL;");
console.log(`Worker ${workerData.workerNo} writing ${workerData.numberOfWrites} items into ${workerData.dbFile}...`)
for (let i = 0; i < workerData.numberOfWrites; i++) {
db.exec(`INSERT INTO data (info) VALUES (${i})`);
}
db.close();
npm start