|
2 | 2 | // Use of this source code is governed by a BSD-style license that can be
|
3 | 3 | // found in the LICENSE file.
|
4 | 4 |
|
5 |
| -const inJetStreamRunner = typeof globalThis.benchmarkTime !== "undefined"; |
6 |
| -if (!inJetStreamRunner) { |
7 |
| - load("polyfills.js"); |
| 5 | +// First, some polyfills for missing browser APIs in JavaScript shells. |
| 6 | +// Since the generated JavaScript code of SQLite immediately uses some of them, |
| 7 | +// we need to load and run this code before the generated `speedtest1.js` in the |
| 8 | +// JetStream driver. |
8 | 9 |
|
9 |
| - // Exports `sqlite3InitModule()` and contains the main code. |
10 |
| - load("build/jswasm/speedtest1.js"); |
| 10 | +// Empty `URLSearchParams` has just the same interface as a `Map`. |
| 11 | +globalThis.URLSearchParams = Map; |
11 | 12 |
|
12 |
| - // Load Wasm binary from disk. |
13 |
| - globalThis.Module = { |
14 |
| - wasmBinary: read("build/jswasm/speedtest1.wasm", "binary"), |
15 |
| - }; |
| 13 | +// `TextEncoder` and `TextDecoder`. These are called only a few times with short |
| 14 | +// ASCII strings, so this is sufficient and not performance-critical. |
| 15 | +class TextEncoder { |
| 16 | + encode(string) { |
| 17 | + return Uint8Array.from(string, (char) => { |
| 18 | + let byte = char.codePointAt(0); |
| 19 | + if (byte > 0x7f) |
| 20 | + throw new Error("TextEncoder polyfill only supports ASCII"); |
| 21 | + return byte; |
| 22 | + }); |
| 23 | + } |
| 24 | +} |
| 25 | +class TextDecoder { |
| 26 | + decode(array) { |
| 27 | + for (let byte of array) { |
| 28 | + if (byte > 0x7f) |
| 29 | + throw new Error("TextDecoder polyfill only supports ASCII"); |
| 30 | + } |
| 31 | + return String.fromCharCode.apply(null, array); |
| 32 | + } |
16 | 33 | }
|
17 | 34 |
|
| 35 | +// Now, some configuration options for when we initialize SQLite. |
| 36 | + |
| 37 | +// Use JetStream functions instead of `console.log` and friends. |
| 38 | +globalThis.sqlite3ApiConfig = { |
| 39 | + log: print, |
| 40 | + debug: print, |
| 41 | + warn: print, |
| 42 | + error: print, |
| 43 | +}; |
| 44 | + |
18 | 45 | // Make sure we never initialize OPFS by removing one of it's APIs (see
|
19 | 46 | // `installOpfsVfs` in the generated JavaScript code of sqlite).
|
20 | 47 | // We never want to use it anyway (see VFS config below) and this way we don't
|
21 | 48 | // waste cycles on the browser runner to initialize it.
|
22 | 49 | delete globalThis.FileSystemHandle;
|
23 | 50 |
|
24 |
| -// Simplified from inline JavaScript in `speedtest1.html`. |
25 |
| -function runTests(sqlite3Module) { |
26 |
| - // Configure the VFS to use. |
27 |
| - // Don't use OPFS, WASMFS (which is on top of OPFS), or kvvfs, since they all |
28 |
| - // use persistent browser storage (localStorage or OPFS), which is not |
29 |
| - // available in JavaScript shells. |
30 |
| - // Also don't use memfs, since that crashes with a NULL function pointer. |
31 |
| - // Instead, make the default VFS explicit. |
32 |
| - const capi = sqlite3Module.capi |
33 |
| - console.log("Available SQLite VFS:", capi.sqlite3_js_vfs_list()); |
34 |
| - const vfs = "unix"; |
35 |
| - console.log("Using VFS:", vfs); |
36 |
| - const pVfs = capi.sqlite3_vfs_find(vfs); |
37 |
| - if (!pVfs) { |
38 |
| - console.error("Error: Unknown VFS:", vfs); |
39 |
| - return; |
40 |
| - } |
| 51 | +class Benchmark { |
| 52 | + sqlite3Module; |
41 | 53 |
|
42 |
| - // These arguments should match the upstream browser runner `speedtest1.html`. |
43 |
| - let argv = [ |
44 |
| - "speedtest1", |
45 |
| - "--singlethread", |
46 |
| - //"--nomutex", |
47 |
| - //"--nosync", |
48 |
| - //"--memdb", // note that memdb trumps the filename arg |
49 |
| - "--nomemstat", |
50 |
| - "--big-transactions" /*important for tests 410 and 510!*/, |
51 |
| - "--size", "20", // To speedup, default is 100 (and takes about 4s). |
52 |
| - "--vfs", vfs, // See VFS comment above. |
53 |
| - ]; |
| 54 | + async runIteration() { |
| 55 | + if (!this.sqlite3Module) { |
| 56 | + // Defined in the generated SQLite JavaScript code. |
| 57 | + // Different in details but seemingly related/inspired by Emscripten code. |
| 58 | + this.sqlite3Module = await sqlite3InitModule(Module); |
| 59 | + } |
54 | 60 |
|
55 |
| - console.log("Calling main with argv:", argv); |
56 |
| - const wasm = sqlite3Module.wasm; |
57 |
| - wasm.scopedAllocPush(); // Required for `scopedAllocMainArgv()`. |
58 |
| - wasm.xCall("wasm_main", argv.length, wasm.scopedAllocMainArgv(argv)); |
59 |
| - wasm.scopedAllocPop(); |
60 |
| -} |
| 61 | + // The following is simplified from inline JavaScript in `speedtest1.html`. |
| 62 | + |
| 63 | + // Configure the VFS to use. |
| 64 | + // Don't use OPFS, WASMFS (which is on top of OPFS), or kvvfs, since they |
| 65 | + // all use persistent browser storage (localStorage or OPFS), which is not |
| 66 | + // available in JavaScript shells. |
| 67 | + // Also don't use memfs, since that crashes with a NULL function pointer. |
| 68 | + // Instead, make the default VFS explicit. |
| 69 | + const capi = this.sqlite3Module.capi |
| 70 | + print("Available SQLite VFS:", capi.sqlite3_js_vfs_list()); |
| 71 | + const vfs = "unix"; |
| 72 | + print("Using VFS:", vfs); |
| 73 | + const pVfs = capi.sqlite3_vfs_find(vfs); |
| 74 | + if (!pVfs) { |
| 75 | + throw new Error("Unknown VFS:", vfs); |
| 76 | + } |
61 | 77 |
|
62 |
| -async function doRun() { |
63 |
| - let start = benchmarkTime(); |
64 |
| - const sqliteModule = await sqlite3InitModule(Module); |
65 |
| - reportCompileTime(benchmarkTime() - start); |
| 78 | + // These arguments should match the upstream browser runner in |
| 79 | + // `speedtest1.html`, except for the --size parameter. |
| 80 | + let argv = [ |
| 81 | + "speedtest1", |
| 82 | + "--singlethread", |
| 83 | + //"--nomutex", |
| 84 | + //"--nosync", |
| 85 | + //"--memdb", // note that memdb trumps the filename arg |
| 86 | + "--nomemstat", |
| 87 | + "--big-transactions" /*important for tests 410 and 510!*/, |
| 88 | + "--size", "10", // To speedup, default is 100 (and takes about 4s). |
| 89 | + "--vfs", vfs, // See VFS comment above. |
| 90 | + ]; |
66 | 91 |
|
67 |
| - start = benchmarkTime(); |
68 |
| - runTests(sqliteModule); |
69 |
| - reportRunTime(benchmarkTime() - start); |
70 |
| -} |
71 |
| -if (!inJetStreamRunner) { |
72 |
| - sqlite3InitModule(Module).then(runTests); |
| 92 | + print("Calling main with argv:", argv); |
| 93 | + const wasm = this.sqlite3Module.wasm; |
| 94 | + wasm.scopedAllocPush(); // Required for `scopedAllocMainArgv()`. |
| 95 | + wasm.xCall("wasm_main", argv.length, wasm.scopedAllocMainArgv(argv)); |
| 96 | + wasm.scopedAllocPop(); |
| 97 | + } |
73 | 98 | }
|
0 commit comments