<!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>
<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>
<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{
ln = document.createTextNode(args.join(' ')+'\n');
}
eOut.append(ln);
};
const 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(' ');
};
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' : '')
);
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);
flags["--autovacuum"] = "Enable AUTOVACUUM mode";
flags["--big-transactions"] = "Important for tests 410 and 510!";
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["--incrvacuum"] = "Enable incremenatal vacuum mode";
flags["--memdb"] = "Use an in-memory database";
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["--reprepare"] = "Reprepare each statement upon every invocation";
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["--strict"] = "Use STRICT table where appropriate";
flags["--stats"] = "Show statistics at the end";
flags["--trace"] = "Turn on SQL tracing";
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.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');
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;
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>