diff options
author | stephan <stephan@noemail.net> | 2022-09-19 17:09:09 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2022-09-19 17:09:09 +0000 |
commit | f815011a085e86117da3e28f8281fb13cf1bcdf9 (patch) | |
tree | a408bdfa2cb7c04f6ddd7bb1571e3bed92aa8b39 /ext/wasm/api/sqlite3-api-opfs.js | |
parent | 61418d5a679f11bbf3517431777c14b30252bd75 (diff) | |
download | sqlite-f815011a085e86117da3e28f8281fb13cf1bcdf9.tar.gz sqlite-f815011a085e86117da3e28f8281fb13cf1bcdf9.zip |
Cut the speedtest1 runtime of the OPFS VFS proxy by approximately 3/4ths via xRead/xWrite buffer-copying optimizations. Still slower than the WASMFS impl by approx. 1/5th.
FossilOrigin-Name: fb7f287310d74a3e236125ae9c49b859f9263c29ae85161c1bcf9dd0778d8a51
Diffstat (limited to 'ext/wasm/api/sqlite3-api-opfs.js')
-rw-r--r-- | ext/wasm/api/sqlite3-api-opfs.js | 94 |
1 files changed, 81 insertions, 13 deletions
diff --git a/ext/wasm/api/sqlite3-api-opfs.js b/ext/wasm/api/sqlite3-api-opfs.js index 62aad0c4b..b7e6887f6 100644 --- a/ext/wasm/api/sqlite3-api-opfs.js +++ b/ext/wasm/api/sqlite3-api-opfs.js @@ -134,6 +134,34 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) by the Promise setup and, on success, installed as sqlite3.opfs. */ const opfsUtil = Object.create(null); + /** + Not part of the public API. Solely for internal/development + use. + */ + opfsUtil.metrics = { + dump: function(){ + let k, n = 0, t = 0; + for(k in metrics){ + const m = metrics[k]; + n += m.count; + t += m.time; + m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0; + m.avgWait = (m.count && m.wait) ? (m.wait / m.count) : 0; + } + console.log("metrics for",self.location.href,":",metrics, + "\nTotal of",n,"op(s) for",t,"ms"); + }, + reset: function(){ + let k; + const r = (m)=>(m.count = m.time = m.wait = 0); + for(k in state.opIds){ + r(metrics[k] = Object.create(null)); + } + [ // timed routines which are not in state.opIds + 'xFileControl' + ].forEach((k)=>r(metrics[k] = Object.create(null))); + } + }/*metrics*/; /** State which we send to the async-api Worker or share with it. @@ -165,6 +193,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) state.fbInt64Offset = state.fileBufferSize - 8 /*spot in fileHandle.sab to store an int64 result */; state.opIds = Object.create(null); + const metrics = Object.create(null); { let i = 0; state.opIds.xAccess = i++; @@ -180,6 +209,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) state.opIds.xWrite = i++; state.opIds.mkdir = i++; state.opSAB = new SharedArrayBuffer(i * 4/*sizeof int32*/); + opfsUtil.metrics.reset(); } state.sq3Codes = Object.create(null); @@ -207,9 +237,11 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) given operation's signature in the async API counterpart. */ const opRun = (op,args)=>{ + const t = performance.now(); Atomics.store(state.opSABView, state.opIds[op], -1); wMsg(op, args); Atomics.wait(state.opSABView, state.opIds[op], -1); + metrics[op].wait += performance.now() - t; return Atomics.load(state.opSABView, state.opIds[op]); }; @@ -338,7 +370,20 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) tgt.ondispose.__removeFuncList.push(memKey, pFunc); return (n,f)=>callee(tgt, n, f); }/*installMethod*/; - + + const opTimer = Object.create(null); + opTimer.op = undefined; + opTimer.start = undefined; + const mTimeStart = (op)=>{ + opTimer.start = performance.now(); + opTimer.op = op; + //metrics[op] || toss("Maintenance required: missing metrics for",op); + ++metrics[op].count; + }; + const mTimeEnd = ()=>( + metrics[opTimer.op].time += performance.now() - opTimer.start + ); + /** Impls for the sqlite3_io_methods methods. Maintenance reminder: members are in alphabetical order to simplify finding them. @@ -351,6 +396,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) return 0; }, xClose: function(pFile){ + mTimeStart('xClose'); let rc = 0; const f = __openFiles[pFile]; if(f){ @@ -358,22 +404,29 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) rc = opRun('xClose', pFile); if(f.sq3File) f.sq3File.dispose(); } + mTimeEnd(); return rc; }, xDeviceCharacteristics: function(pFile){ //debug("xDeviceCharacteristics(",pFile,")"); return capi.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN; }, - xFileControl: function(pFile,op,pArg){ - //debug("xFileControl(",arguments,") is a no-op"); + xFileControl: function(pFile, opId, pArg){ + mTimeStart('xFileControl'); + if(capi.SQLITE_FCNTL_SYNC===opId){ + return opRun('xSync', {fid:pFile, flags:0}); + } + mTimeEnd(); return capi.SQLITE_NOTFOUND; }, xFileSize: function(pFile,pSz64){ + mTimeStart('xFileSize'); const rc = opRun('xFileSize', pFile); if(!isWorkerErrCode(rc)){ const f = __openFiles[pFile]; - wasm.setMemValue(pSz64, f.sabViewFileSize.getBigInt64(0) ,'i64'); + wasm.setMemValue(pSz64, f.sabViewFileSize.getBigInt64(0,true) ,'i64'); } + mTimeEnd(); return rc; }, xLock: function(pFile,lockType){ @@ -383,26 +436,31 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) }, xRead: function(pFile,pDest,n,offset){ /* int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst) */ + mTimeStart('xRead'); const f = __openFiles[pFile]; let rc; try { // FIXME(?): block until we finish copying the xRead result buffer. How? rc = opRun('xRead',{fid:pFile, n, offset}); if(0===rc || capi.SQLITE_IOERR_SHORT_READ===rc){ - let i = 0; - for(; i < n; ++i) wasm.setMemValue(pDest + i, f.sabView[i]); + // set() seems to be the fastest way to copy this... + wasm.heap8u().set(f.sabView.subarray(0, n), pDest); } }catch(e){ error("xRead(",arguments,") failed:",e,f); rc = capi.SQLITE_IOERR_READ; } + mTimeEnd(); return rc; }, xSync: function(pFile,flags){ - return opRun('xSync', {fid:pFile, flags}); + return 0; // impl'd in xFileControl(). opRun('xSync', {fid:pFile, flags}); }, xTruncate: function(pFile,sz64){ - return opRun('xTruncate', {fid:pFile, size: sz64}); + mTimeStart('xTruncate'); + const rc = opRun('xTruncate', {fid:pFile, size: sz64}); + mTimeEnd(); + return rc; }, xUnlock: function(pFile,lockType){ //2022-09: OPFS handles lock when opened @@ -411,16 +469,19 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) }, xWrite: function(pFile,pSrc,n,offset){ /* int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst) */ + mTimeStart('xWrite'); const f = __openFiles[pFile]; + let rc; try { - let i = 0; // FIXME(?): block from here until we finish the xWrite. How? - for(; i < n; ++i) f.sabView[i] = wasm.getMemValue(pSrc+i); - return opRun('xWrite',{fid:pFile, n, offset}); + f.sabView.set(wasm.heap8u().subarray(pSrc, pSrc+n)); + rc = opRun('xWrite',{fid:pFile, n, offset}); }catch(e){ error("xWrite(",arguments,") failed:",e,f); - return capi.SQLITE_IOERR_WRITE; + rc = capi.SQLITE_IOERR_WRITE; } + mTimeEnd(); + return rc; } }/*ioSyncWrappers*/; @@ -430,8 +491,10 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) */ const vfsSyncWrappers = { xAccess: function(pVfs,zName,flags,pOut){ + mTimeStart('xAccess'); const rc = opRun('xAccess', wasm.cstringToJs(zName)); wasm.setMemValue(pOut, rc ? 0 : 1, 'i32'); + mTimeEnd(); return 0; }, xCurrentTime: function(pVfs,pOut){ @@ -448,9 +511,11 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) return 0; }, xDelete: function(pVfs, zName, doSyncDir){ + mTimeStart('xDelete'); opRun('xDelete', {filename: wasm.cstringToJs(zName), syncDir: doSyncDir}); /* We're ignoring errors because we cannot yet differentiate between harmless and non-harmless failures. */ + mTimeEnd(); return 0; }, xFullPathname: function(pVfs,zName,nOut,pOut){ @@ -469,6 +534,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) }, //xSleep is optionally defined below xOpen: function f(pVfs, zName, pFile, flags, pOutFlags){ + mTimeStart('xOpen'); if(!f._){ f._ = { fileTypes: { @@ -518,6 +584,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) args.sq3File.$pMethods = opfsIoMethods.pointer; args.ba = new Uint8Array(args.sab); } + mTimeEnd(); return rc; }/*xOpen()*/ }/*vfsSyncWrappers*/; @@ -600,7 +667,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) }; opfsUtil.OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype); } - + /** Potential TODOs: @@ -670,6 +737,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) } }/*sanityCheck()*/; + W.onmessage = function({data}){ //log("Worker.onmessage:",data); switch(data.type){ |