mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 18:25:13 +08:00
`all()`, `get()` and `iterate()` built each row with the `Object::New()` overload that takes names and values. That overload always returns a dictionary-mode object, so no two rows shared a map and every property read was a hash lookup. Build rows from a `DictionaryTemplate` cached on the statement in place of the column names, invalidated on re-prepare. Rows keep their null prototype. Statements whose column names a template cannot express (array indices, duplicates, non-ASCII names, which the template interns as Latin-1) or with more than 64 columns keep the previous path. Add a benchmark that reads every column of each row, since the existing ones only measure building rows. Fixes: https://github.com/nodejs/node/issues/65799 Assisted-by: Claude Signed-off-by: Guilherme Araújo <arauujogui@gmail.com> PR-URL: https://github.com/nodejs/node/pull/66385 Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
45 lines
1.3 KiB
JavaScript
45 lines
1.3 KiB
JavaScript
'use strict';
|
|
const common = require('../common.js');
|
|
const sqlite = require('node:sqlite');
|
|
const assert = require('assert');
|
|
|
|
const bench = common.createBenchmark(main, {
|
|
n: [1e4],
|
|
rows: [1, 100],
|
|
method: ['all', 'iterate', 'get'],
|
|
returnArrays: [0, 1],
|
|
});
|
|
|
|
function main(conf) {
|
|
const db = new sqlite.Database(':memory:');
|
|
db.exec(
|
|
'CREATE TABLE foo (text_column TEXT, integer_column INTEGER, real_column REAL, blob_column BLOB)',
|
|
);
|
|
const insert = db.prepare('INSERT INTO foo VALUES (?, ?, ?, ?)');
|
|
for (let i = 0; i < conf.rows; i++) {
|
|
insert.run(`text ${i}`, i, i / 3, Buffer.from('example blob data'));
|
|
}
|
|
|
|
const stmt = db.prepare(`SELECT * FROM foo LIMIT ${conf.rows}`);
|
|
stmt.setReturnArrays(conf.returnArrays === 1);
|
|
|
|
// Each row is built and then has every column read once.
|
|
const read = conf.returnArrays ?
|
|
(row) => row[0].length + row[1] + row[2] + row[3].length :
|
|
(row) => row.text_column.length + row.integer_column +
|
|
row.real_column + row.blob_column.length;
|
|
|
|
let sum = 0;
|
|
bench.start();
|
|
for (let i = 0; i < conf.n; i++) {
|
|
if (conf.method === 'get') {
|
|
sum += read(stmt.get());
|
|
} else {
|
|
for (const row of stmt[conf.method]()) sum += read(row);
|
|
}
|
|
}
|
|
bench.end(conf.n);
|
|
|
|
assert.ok(sum > 0);
|
|
}
|