summaryrefslogtreecommitdiff
path: root/chromium/third_party/sqlite/src/ext/wasm/speedtest1-worker.html
blob: cd0fdb027cb27ad965bdbae0891fd4976a62509f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
    <link rel="stylesheet" href="common/emscripten.css"/>
    <link rel="stylesheet" href="common/testing.css"/>
    <title>speedtest1.wasm Worker</title>
  </head>
  <body>
    <header id='titlebar'>speedtest1.wasm Worker</header>
    <div>See also: <a href='speedtest1.html'>A main-thread variant of this page.</a></div>
    <!-- emscripten bits -->
    <figure id="module-spinner">
      <div class="spinner"></div>
      <div class='center'><strong>Initializing app...</strong></div>
      <div class='center'>
        On a slow internet connection this may take a moment.  If this
        message displays for "a long time", intialization may have
        failed and the JavaScript console may contain clues as to why.
      </div>
    </figure>
    <div class="emscripten" id="module-status">Downloading...</div>
    <div class="emscripten">
      <progress value="0" max="100" id="module-progress" hidden='1'></progress>  
    </div><!-- /emscripten bits -->
    <fieldset id='ui-controls' class='hidden'>
      <legend>Options</legend>
      <div id='toolbar'>
        <div id='toolbar-select'>
          <select id='select-flags' size='10' multiple></select>
          <div>The following flags can be passed as URL parameters:
            vfs=NAME, size=N, journal=MODE, cachesize=SIZE
          </div>
        </div>
        <div class='toolbar-inner-vertical'>
          <div id='toolbar-selected-flags'></div>
          <div class='toolbar-inner-vertical'>
            <span>&rarr; <a id='link-main-thread' href='#' target='speedtest-main'
                            title='Start speedtest1.html with the selected flags'>speedtest1</a>
            </span>
            <span class='hidden'>&rarr; <a id='link-wasmfs' href='#' target='speedtest-wasmfs'
                            title='Start speedtest1-wasmfs.html with the selected flags'>speedtest1-wasmfs</a>
            </span>
            <span>&rarr; <a id='link-kvvfs' href='#' target='speedtest-kvvfs'
                            title='Start kvvfs speedtest1 with the selected flags'>speedtest1-kvvfs</a>
            </span>
          </div>
        </div>
        <div class='toolbar-inner-vertical' id='toolbar-runner-controls'>
          <button id='btn-reset-flags'>Reset Flags</button>
          <button id='btn-output-clear'>Clear output</button>
          <button id='btn-run'>Run</button>
        </div>
      </div>
    </fieldset>
    <div>
      <span class='input-wrapper'>
        <input type='checkbox' class='disable-during-eval' id='cb-reverse-log-order' checked></input>
        <label for='cb-reverse-log-order' id='lbl-reverse-log-order'>Reverse log order</label>
      </span>
    </div>
    <div id='test-output'>
    </div>
    <div id='tips'>
      <strong>Tips:</strong>
      <ul>
        <li>Control-click the flags to (de)select multiple flags.</li>
        <li>The <tt>--big-transactions</tt> flag is important for two
          of the bigger tests. Without it, those tests create a
          combined total of 140k implicit transactions, reducing their
          speed to an absolute crawl, especially when WASMFS is
          activated.
        </li>
        <li>The easiest way to try different optimization levels is,
          from this directory:
          <pre>$ rm -f jswasm/speedtest1.js; make -e emcc_opt='-O2' speedtest1</pre>
          Then reload this page. -O2 seems to consistently produce the fastest results.
        </li>
        </ul>
    </div>
    <style>
      #test-output {
          white-space: break-spaces;
          overflow: auto;
      }
      div#tips { margin-top: 1em; }
      #toolbar {
          display: flex;
          flex-direction: row;
          flex-wrap: wrap;
      }
      #toolbar > * {
          margin: 0 0.5em;
      }
      .toolbar-inner-vertical {
          display: flex;
          flex-direction: column;
          justify-content: space-between;
      }
      #toolbar-select {
          display: flex;
          flex-direction: column;
      }
      .toolbar-inner-vertical > *, #toolbar-select > * {
          margin: 0.2em 0;
      }
      #select-flags > option {
          white-space: pre;
          font-family: monospace;
      }
      fieldset {
          border-radius: 0.5em;
      }
      #toolbar-runner-controls { flex-grow: 1 }
      #toolbar-runner-controls > * { flex: 1 0 auto }
      #toolbar-selected-flags::before {
        font-family: initial;
        content:"Selected flags: ";
      }
      #toolbar-selected-flags {
        display: flex;
        flex-direction: column;
        font-family: monospace;
        justify-content: flex-start;
      }
    </style>
    <script>(function(){
    'use strict';
    const E = (sel)=>document.querySelector(sel);
    const eOut = E('#test-output');
    const log2 = function(cssClass,...args){
        let ln;
        if(1 || cssClass){
            ln = document.createElement('div');
            if(cssClass) ln.classList.add(cssClass);
            ln.append(document.createTextNode(args.join(' ')));
        }else{
            // This doesn't work with the "reverse order" option!
            ln = document.createTextNode(args.join(' ')+'\n');
        }
        eOut.append(ln);
    };
    const log = (...args)=>{
        //console.log(...args);
        log2('', ...args);
    };
    const logErr = function(...args){
        console.error(...args);
        log2('error', ...args);
    };
    const logWarn = function(...args){
        console.warn(...args);
        log2('warning', ...args);
    };

    const spacePad = function(str,len=21){
        if(str.length===len) return str;
        else if(str.length>len) return str.substr(0,len);
        const a = []; a.length = len - str.length;
        return str+a.join(' ');
    };
    // OPTION elements seem to ignore white-space:pre, so do this the hard way...
    const nbspPad = function(str,len=21){
        if(str.length===len) return str;
        else if(str.length>len) return str.substr(0,len);
        const a = []; a.length = len - str.length;
        return str+a.join('&nbsp;');
    };

    const urlParams = new URL(self.location.href).searchParams;
    const W = new Worker(
        "speedtest1-worker.js?sqlite3.dir=jswasm"+
            (urlParams.has('opfs-verbose') ? '&opfs-verbose' : '')
    );
    const mPost = function(msgType,payload){
        W.postMessage({type: msgType, data: payload});
    };

    const eFlags = E('#select-flags');
    const eSelectedFlags = E('#toolbar-selected-flags');
    const eLinkMainThread = E('#link-main-thread');
    const eLinkWasmfs = E('#link-wasmfs');
    const eLinkKvvfs = E('#link-kvvfs');
    const getSelectedFlags = ()=>{
        const f = Array.prototype.map.call(eFlags.selectedOptions, (v)=>v.value);
        [
            'size', 'vfs', 'journal', 'cachesize'
        ].forEach(function(k){
            if(urlParams.has(k)) f.push('--'+k, urlParams.get(k));
        });
        return f;
    };
    const updateSelectedFlags = function(){
        eSelectedFlags.innerText = '';
        const flags = getSelectedFlags();
        flags.forEach(function(f){
            const e = document.createElement('span');
            e.innerText = f;
            eSelectedFlags.appendChild(e);
        });
        const rxStripDash = /^(-+)?/;
        const comma = flags.join(',');
        eLinkMainThread.setAttribute('target', 'speedtest1-main-'+comma);
        eLinkMainThread.href = 'speedtest1.html?flags='+comma;
        eLinkWasmfs.setAttribute('target', 'speedtest1-wasmfs-'+comma);
        eLinkWasmfs.href = 'speedtest1-wasmfs.html?flags='+comma;
        eLinkKvvfs.setAttribute('target', 'speedtest1-kvvfs-'+comma);
        eLinkKvvfs.href = 'speedtest1.html?vfs=kvvfs&flags='+comma;
    };
    eFlags.addEventListener('change', updateSelectedFlags );
    {
        const flags = Object.create(null);
        /* TODO? Flags which require values need custom UI
           controls and some of them make little sense here
           (e.g. --script FILE). */
        flags["--autovacuum"] = "Enable AUTOVACUUM mode";
        flags["--big-transactions"] = "Important for tests 410 and 510!";
        //flags["--cachesize"] = "N       Set the cache size to N pages";
        flags["--checkpoint"] = "Run PRAGMA wal_checkpoint after each test case";
        flags["--exclusive"] = "Enable locking_mode=EXCLUSIVE";
        flags["--explain"] = "Like --sqlonly but with added EXPLAIN keywords";
        //flags["--heap"] = "SZ MIN       Memory allocator uses SZ bytes & min allocation MIN";
        flags["--incrvacuum"] = "Enable incremenatal vacuum mode";
        //flags["--journal"] = "M         Set the journal_mode to M";
        //flags["--key"] = "KEY           Set the encryption key to KEY";
        //flags["--lookaside"] = "N SZ    Configure lookaside for N slots of SZ bytes each";
        flags["--memdb"] = "Use an in-memory database";
        //flags["--mmap"] = "SZ           MMAP the first SZ bytes of the database file";
        flags["--multithread"] = "Set multithreaded mode";
        flags["--nomemstat"] = "Disable memory statistics";
        flags["--nomutex"] = "Open db with SQLITE_OPEN_NOMUTEX";
        flags["--nosync"] = "Set PRAGMA synchronous=OFF";
        flags["--notnull"] = "Add NOT NULL constraints to table columns";
        //flags["--output"] = "FILE       Store SQL output in FILE";
        //flags["--pagesize"] = "N        Set the page size to N";
        //flags["--pcache"] = "N SZ       Configure N pages of pagecache each of size SZ bytes";
        //flags["--primarykey"] = "Use PRIMARY KEY instead of UNIQUE where appropriate";
        //flags["--repeat"] = "N          Repeat each SELECT N times (default: 1)";
        flags["--reprepare"] = "Reprepare each statement upon every invocation";
        //flags["--reserve"] = "N         Reserve N bytes on each database page";
        //flags["--script"] = "FILE       Write an SQL script for the test into FILE";
        flags["--serialized"] = "Set serialized threading mode";
        flags["--singlethread"] = "Set single-threaded mode - disables all mutexing";
        flags["--sqlonly"] = "No-op.  Only show the SQL that would have been run.";
        flags["--shrink-memory"] = "Invoke sqlite3_db_release_memory() frequently.";
        //flags["--size"] = "N            Relative test size.  Default=100";
        flags["--strict"] = "Use STRICT table where appropriate";
        flags["--stats"] = "Show statistics at the end";
        //flags["--temp"] = "N            N from 0 to 9.  0: no temp table. 9: all temp tables";
        //flags["--testset"] = "T         Run test-set T (main, cte, rtree, orm, fp, debug)";
        flags["--trace"] = "Turn on SQL tracing";
        //flags["--threads"] = "N         Use up to N threads for sorting";
        /*
          The core API's WASM build does not support UTF16, but in
          this app it's not an issue because the data are not crossing
          JS/WASM boundaries.
        */
        flags["--utf16be"] = "Set text encoding to UTF-16BE";
        flags["--utf16le"] = "Set text encoding to UTF-16LE";
        flags["--verify"] = "Run additional verification steps.";
        flags["--without"] = "rowid     Use WITHOUT ROWID where appropriate";
        const preselectedFlags = [
            '--big-transactions',
            '--singlethread'
        ];
        if(urlParams.has('flags')){
            preselectedFlags.push(...urlParams.get('flags').split(','));
        }
        if('opfs'!==urlParams.get('vfs')){
            preselectedFlags.push('--memdb');
        }
        Object.keys(flags).sort().forEach(function(f){
            const opt = document.createElement('option');
            eFlags.appendChild(opt);
            const lbl = nbspPad(f)+flags[f];
            //opt.innerText = lbl;
            opt.innerHTML = lbl;
            opt.value = f;
            if(preselectedFlags.indexOf(f) >= 0) opt.selected = true;
        });    
        const cbReverseLog = E('#cb-reverse-log-order');
        const lblReverseLog = E('#lbl-reverse-log-order');
        if(cbReverseLog.checked){
            lblReverseLog.classList.add('warning');
            eOut.classList.add('reverse');
        }
        cbReverseLog.addEventListener('change', function(){
            if(this.checked){
                eOut.classList.add('reverse');
                lblReverseLog.classList.add('warning');
            }else{
                eOut.classList.remove('reverse');
                lblReverseLog.classList.remove('warning');
            }
        }, false);
        updateSelectedFlags();
    }
    E('#btn-output-clear').addEventListener('click', ()=>{
        eOut.innerText = '';
    });
    E('#btn-reset-flags').addEventListener('click',()=>{
        eFlags.value = '';
        updateSelectedFlags();
    });
    E('#btn-run').addEventListener('click',function(){
        log("Running speedtest1. UI controls will be disabled until it completes.");
        mPost('run', getSelectedFlags());
    });

    const eControls = E('#ui-controls');
    /** Update Emscripten-related UI elements while loading the module. */
    const updateLoadStatus = function f(text){
        if(!f.last){
            f.last = { text: '', step: 0 };
            const E = (cssSelector)=>document.querySelector(cssSelector);
            f.ui = {
                status: E('#module-status'),
                progress: E('#module-progress'),
                spinner: E('#module-spinner')
            };
        }
        if(text === f.last.text) return;
        f.last.text = text;
        if(f.ui.progress){
            f.ui.progress.value = f.last.step;
            f.ui.progress.max = f.last.step + 1;
        }
        ++f.last.step;
        if(text) {
            f.ui.status.classList.remove('hidden');
            f.ui.status.innerText = text;
        }else{
            if(f.ui.progress){
                f.ui.progress.remove();
                f.ui.spinner.remove();
                delete f.ui.progress;
                delete f.ui.spinner;
            }
            f.ui.status.classList.add('hidden');
        }
    };

    W.onmessage = function(msg){
        msg = msg.data;
        switch(msg.type){
            case 'ready':
                log("Worker is ready.");
                eControls.classList.remove('hidden');
                break;
            case 'stdout': log(msg.data); break;
            case 'stdout': logErr(msg.data); break;
            case 'run-start':
                eControls.disabled = true;
                log("Running speedtest1 with argv =",msg.data.join(' '));
                break;
            case 'run-end':
                log("speedtest1 finished.");
                eControls.disabled = false;
                // app output is in msg.data
                break;
            case 'error': logErr(msg.data); break;
            case 'load-status': updateLoadStatus(msg.data); break;
            default:
                logErr("Unhandled worker message type:",msg);
                break;
        }
    };
})();</script>
  </body>
</html>