mirror of
https://github.com/lana-k/sqliteviz.git
synced 2025-12-06 18:18:53 +08:00
138 lines
3.5 KiB
JavaScript
138 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
|
|
}
|