1
0
mirror of https://github.com/lana-k/sqliteviz.git synced 2025-12-06 18:18:53 +08:00
Files
sqliteviz/lib/sql-js/benchmark/suite.js

141 lines
3.5 KiB
JavaScript

import benchmark from 'benchmark'
import initSqlJs from 'sql.js'
import lodash from 'lodash'
import Papa from 'papaparse'
import useragent from 'ua-parser-js'
describe('SQLite build benchmark', function () {
let parsedCsv
let sqlModule
let selectDb
before(async function () {
parsedCsv = await parseCsv('http://localhost:9876/base/sample.csv')
sqlModule = await initSqlJs()
selectDb = new sqlModule.Database()
importToTable(selectDb, parsedCsv)
})
function benchmarkImport () {
const db = new sqlModule.Database()
try {
importToTable(db, parsedCsv)
} finally {
db.close()
}
}
function benchmarkSelect () {
const result = selectDb.exec(`
SELECT county, AVG(avg_depth) avg_depth_c
FROM (
SELECT s.county, s.town, COUNT(*) cnt, AVG(s.DrilledDepth) avg_depth
FROM csv_import s
JOIN csv_import USING(hole)
WHERE s.town IS NOT NULL
GROUP BY 1, 2
ORDER BY 4 DESC
)
GROUP BY 1
ORDER BY 2 DESC
`)
console.assert(result.values.length == 56, 'Unexpected size of result set')
}
it('run', async function () {
const suite = createSuite()
suite.add('import', { initCount: 3, minSamples: 50, fn: benchmarkImport })
suite.add('select', { initCount: 3, minSamples: 50, fn: benchmarkSelect })
await run(suite)
})
})
function importToTable (db, parsedCsv, chunkSize = 1024) {
const columnListString = parsedCsv.meta.fields.join(', ')
db.exec(`CREATE TABLE csv_import(${columnListString})`)
const params = parsedCsv.meta.fields.map(name => '?').join(', ')
const insertStmt = db.prepare(`INSERT INTO csv_import VALUES(${params})`)
chunkArray(parsedCsv.data, chunkSize).map(function (chunk) {
db.exec('BEGIN')
chunk.map(row => insertStmt.run(Object.values(row)))
db.exec('COMMIT')
})
}
class PromiseWrapper {
constructor() {
this.promise = new Promise((resolve, reject) => {
this.reject = reject
this.resolve = resolve
})
}
}
function parseCsv(url) {
return new Promise((resolve, reject) => {
Papa.parse(url, {
header: true,
download: true,
skipEmptyLines: 'greedy',
complete: results => resolve(results),
error: (error, file) => reject(error)
})
})
}
function chunkArray (arr, size) {
return arr.reduce(function (result, value, index) {
const chunkIndex = Math.floor(index / size)
if(!(chunkIndex in result)) {
result[chunkIndex] = []
}
result[chunkIndex].push(value)
return result
}, [])
}
function createSuite () {
// Combined workaround from:
// - https://github.com/bestiejs/benchmark.js/issues/106
// - https://github.com/bestiejs/benchmark.js/issues/237
// Benchmark could not pick up lodash otherwise
const bm = benchmark.runInContext({ _: lodash })
// Avoid `ReferenceError: Benchmark is not defined` error because Benchmark is assumed
// to be in window
window.Benchmark = bm
return new bm.Suite()
}
function run (suite) {
const suiteResult = new PromiseWrapper()
suite
.on('cycle', function (event) {
console.info(String(event.target))
})
.on('complete', function () {
console.log(JSON.stringify({
browser: useragent(navigator.userAgent).browser,
result: this.filter('successful')
}))
suiteResult.resolve()
})
.on('error', function (event) {
console.error('Benchmark failed', String(event.target))
suiteResult.reject()
})
.run({async: true})
return suiteResult.promise
}