123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- <!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>→ <a id='link-main-thread' href='#' target='speedtest-main'
- title='Start speedtest1.html with the selected flags'>speedtest1</a>
- </span>
- <span class='hidden'>→ <a id='link-wasmfs' href='#' target='speedtest-wasmfs'
- title='Start speedtest1-wasmfs.html with the selected flags'>speedtest1-wasmfs</a>
- </span>
- <span>→ <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 many
- thousands of implicit transactions, reducing the affected
- tests to an absolute crawl, in particular with OPFS.
- </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(' ');
- };
- const urlParams = new URL(self.location.href).searchParams;
- const W = new Worker(
- "speedtest1-worker.js?sqlite3.dir=jswasm"+
- (urlParams.has('opfs-verbose') ? '&opfs-verbose' : '')+
- (urlParams.has('opfs-disable') ? '&opfs-disable' : '')
- );
- 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(!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 'stderr': 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>
|