Remove extraneous result-code SAB slots. Doc additions.

FossilOrigin-Name: 88de20712bbe3e11ea74af95edc34e9ab9f346f9aa0a30931e5a9e1f96ce57b0
This commit is contained in:
stephan 2022-09-20 10:11:52 +00:00
parent 5e8bb0aa13
commit c9e2602e8f
5 changed files with 96 additions and 87 deletions

View File

@ -434,18 +434,20 @@ push-fiddle: $(fiddle_files)
# painful.
.PHONY: o0 o1 o2 o3 os oz
o-xtra :=
#o-xtra += -flto
o0:
$((MAKE) clean; $(MAKE) -e "emcc_opt=-O0 -flto" fiddle_opt=-O0
$(MAKE) clean; $(MAKE) -e "emcc_opt=-O0 $(o-xtra)" fiddle_opt=-O0
o1:
$(MAKE) clean; $(MAKE) -e "emcc_opt=-O1 -flto" fiddle_opt=-O1
$(MAKE) clean; $(MAKE) -e "emcc_opt=-O1 $(o-xtra)" fiddle_opt=-O1
o2:
$(MAKE) clean; $(MAKE) -e "emcc_opt=-O2 -flto" fiddle_opt=-O2
$(MAKE) clean; $(MAKE) -e "emcc_opt=-O2 $(o-xtra)" fiddle_opt=-O2
o3:
$(MAKE) clean; $(MAKE) -e "emcc_opt=-O3 -flto" fiddle_opt=-O3
$(MAKE) clean; $(MAKE) -e "emcc_opt=-O3 $(o-xtra)" fiddle_opt=-O3
os:
$(MAKE) clean; $(MAKE) -e "emcc_opt=-Os -flto" fiddle_opt=-Os
$(MAKE) clean; $(MAKE) -e "emcc_opt=-Os $(o-xtra)" fiddle_opt=-Os
oz:
$(MAKE) clean; $(MAKE) -e "emcc_opt=-Oz -flto" fiddle_opt=-Oz
$(MAKE) clean; $(MAKE) -e "emcc_opt=-Oz $(o-xtra)" fiddle_opt=-Oz
########################################################################
# Sub-makes...

View File

@ -165,6 +165,38 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
}
}/*metrics*/;
const pDVfs = capi.sqlite3_vfs_find(null)/*pointer to default VFS*/;
const dVfs = pDVfs
? new sqlite3_vfs(pDVfs)
: null /* dVfs will be null when sqlite3 is built with
SQLITE_OS_OTHER. Though we cannot currently handle
that case, the hope is to eventually be able to. */;
const opfsVfs = new sqlite3_vfs();
const opfsIoMethods = new sqlite3_io_methods();
opfsVfs.$iVersion = 2/*yes, two*/;
opfsVfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof;
opfsVfs.$mxPathname = 1024/*sure, why not?*/;
opfsVfs.$zName = wasm.allocCString("opfs");
// All C-side memory of opfsVfs is zeroed out, but just to be explicit:
opfsVfs.$xDlOpen = opfsVfs.$xDlError = opfsVfs.$xDlSym = opfsVfs.$xDlClose = null;
opfsVfs.ondispose = [
'$zName', opfsVfs.$zName,
'cleanup default VFS wrapper', ()=>(dVfs ? dVfs.dispose() : null),
'cleanup opfsIoMethods', ()=>opfsIoMethods.dispose()
];
/**
Pedantic sidebar about opfsVfs.ondispose: the entries in that array
are items to clean up when opfsVfs.dispose() is called, but in this
environment it will never be called. The VFS instance simply
hangs around until the WASM module instance is cleaned up. We
"could" _hypothetically_ clean it up by "importing" an
sqlite3_os_end() impl into the wasm build, but the shutdown order
of the wasm engine and the JS one are undefined so there is no
guaranty that the opfsVfs instance would be available in one
environment or the other when sqlite3_os_end() is called (_if_ it
gets called at all in a wasm build, which is undefined).
*/
/**
State which we send to the async-api Worker or share with it.
This object must initially contain only cloneable or sharable
@ -187,54 +219,64 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
const state = Object.create(null);
state.littleEndian = true;
state.verbose = options.verbose;
/* Size of file I/O buffer block. 64k = max sqlite3 page size. */
state.fileBufferSize =
1024 * 64 /* size of aFileHandle.sab. 64k = max sqlite3 page
size. */;
1024 * 64;
state.sabS11nOffset = state.fileBufferSize;
state.sabS11nSize = 2048;
/**
The size of the block in our SAB for serializing arguments and
result values. Need to be large enough to hold serialized
values of any of the proxied APIs. Filenames are the largest
part but are limited to opfsVfs.$mxPathname bytes.
*/
state.sabS11nSize = opfsVfs.$mxPathname * 2;
/**
The SAB used for all data I/O (files and arg/result s11n).
*/
state.sabIO = new SharedArrayBuffer(
state.fileBufferSize
+ state.sabS11nSize/* arg/result serialization block */
state.fileBufferSize/* file i/o block */
+ state.sabS11nSize/* argument/result serialization block */
);
state.opIds = Object.create(null);
state.rcIds = Object.create(null);
const metrics = Object.create(null);
{
/* Indexes for use in our SharedArrayBuffer... */
let i = 0;
/* SAB slot used to communicate which operation is desired
between both workers. This worker writes to it and the other
listens for changes. */
state.opIds.whichOp = i++;
/* Slot for storing return values. This work listens to that
slot and the other worker writes to it. */
state.opIds.rc = i++;
/* Each function gets an ID which this worker writes to
the whichOp slot. The async-api worker uses Atomic.wait()
on the whichOp slot to figure out which operation to run
next. */
state.opIds.xAccess = i++;
state.rcIds.xAccess = i++;
state.opIds.xClose = i++;
state.rcIds.xClose = i++;
state.opIds.xDelete = i++;
state.rcIds.xDelete = i++;
state.opIds.xDeleteNoWait = i++;
state.rcIds.xDeleteNoWait = i++;
state.opIds.xFileSize = i++;
state.rcIds.xFileSize = i++;
state.opIds.xOpen = i++;
state.rcIds.xOpen = i++;
state.opIds.xRead = i++;
state.rcIds.xRead = i++;
state.opIds.xSleep = i++;
state.rcIds.xSleep = i++;
state.opIds.xSync = i++;
state.rcIds.xSync = i++;
state.opIds.xTruncate = i++;
state.rcIds.xTruncate = i++;
state.opIds.xWrite = i++;
state.rcIds.xWrite = i++;
state.opIds.mkdir = i++;
state.rcIds.mkdir = i++;
state.opIds.xFileControl = i++;
state.rcIds.xFileControl = i++;
state.sabOP = new SharedArrayBuffer(i * 4/*sizeof int32*/);
opfsUtil.metrics.reset();
}
/**
SQLITE_xxx constants to export to the async worker
counterpart...
*/
state.sq3Codes = Object.create(null);
state.sq3Codes._reverse = Object.create(null);
[ // SQLITE_xxx constants to export to the async worker counterpart...
[
'SQLITE_ERROR', 'SQLITE_IOERR',
'SQLITE_NOTFOUND', 'SQLITE_MISUSE',
'SQLITE_IOERR_READ', 'SQLITE_IOERR_SHORT_READ',
@ -252,22 +294,21 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
const isWorkerErrCode = (n)=>!!state.sq3Codes._reverse[n];
/**
Runs the given operation in the async worker counterpart, waits
for its response, and returns the result which the async worker
writes to the given op's index in state.sabOPView. The 2nd argument
must be a single object or primitive value, depending on the
given operation's signature in the async API counterpart.
Runs the given operation (by name) in the async worker
counterpart, waits for its response, and returns the result
which the async worker writes to SAB[state.opIds.rc]. The
2nd and subsequent arguments must be the aruguments for the
async op.
*/
const opRun = (op,...args)=>{
const rcNdx = state.rcIds[op] || toss("Invalid rc ID:",op);
const opNdx = state.opIds[op] || toss("Invalid op ID:",op);
state.s11n.serialize(...args);
Atomics.store(state.sabOPView, rcNdx, -1);
Atomics.store(state.sabOPView, state.opIds.rc, -1);
Atomics.store(state.sabOPView, state.opIds.whichOp, opNdx);
Atomics.notify(state.sabOPView, state.opIds.whichOp) /* async thread will take over here */;
const t = performance.now();
Atomics.wait(state.sabOPView, rcNdx, -1);
const rc = Atomics.load(state.sabOPView, rcNdx);
Atomics.wait(state.sabOPView, state.opIds.rc, -1);
const rc = Atomics.load(state.sabOPView, state.opIds.rc);
metrics[op].wait += performance.now() - t;
return rc;
};
@ -348,38 +389,6 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
Map of sqlite3_file pointers to objects constructed by xOpen().
*/
const __openFiles = Object.create(null);
const pDVfs = capi.sqlite3_vfs_find(null)/*pointer to default VFS*/;
const dVfs = pDVfs
? new sqlite3_vfs(pDVfs)
: null /* dVfs will be null when sqlite3 is built with
SQLITE_OS_OTHER. Though we cannot currently handle
that case, the hope is to eventually be able to. */;
const opfsVfs = new sqlite3_vfs();
const opfsIoMethods = new sqlite3_io_methods();
opfsVfs.$iVersion = 2/*yes, two*/;
opfsVfs.$szOsFile = capi.sqlite3_file.structInfo.sizeof;
opfsVfs.$mxPathname = 1024/*sure, why not?*/;
opfsVfs.$zName = wasm.allocCString("opfs");
// All C-side memory of opfsVfs is zeroed out, but just to be explicit:
opfsVfs.$xDlOpen = opfsVfs.$xDlError = opfsVfs.$xDlSym = opfsVfs.$xDlClose = null;
opfsVfs.ondispose = [
'$zName', opfsVfs.$zName,
'cleanup default VFS wrapper', ()=>(dVfs ? dVfs.dispose() : null),
'cleanup opfsIoMethods', ()=>opfsIoMethods.dispose()
];
/**
Pedantic sidebar about opfsVfs.ondispose: the entries in that array
are items to clean up when opfsVfs.dispose() is called, but in this
environment it will never be called. The VFS instance simply
hangs around until the WASM module instance is cleaned up. We
"could" _hypothetically_ clean it up by "importing" an
sqlite3_os_end() impl into the wasm build, but the shutdown order
of the wasm engine and the JS one are undefined so there is no
guaranty that the opfsVfs instance would be available in one
environment or the other when sqlite3_os_end() is called (_if_ it
gets called at all in a wasm build, which is undefined).
*/
/**
Installs a StructBinder-bound function pointer member of the
@ -798,7 +807,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
vfsSyncWrappers.xAccess(opfsVfs.pointer, zDbFile, 0, pOut);
rc = wasm.getMemValue(pOut,'i32');
if(rc) toss("Expecting 0 from xAccess(",dbFile,") after xDelete().");
log("End of OPFS sanity checks.");
warn("End of OPFS sanity checks.");
}finally{
sq3File.dispose();
wasm.scopedAllocPop(scope);

View File

@ -134,9 +134,9 @@ const getDirForPath = async function f(absFilename, createDirs = false){
and then Atomics.notify()'s it.
*/
const storeAndNotify = (opName, value)=>{
log(opName+"() => notify(",state.rcIds[opName],",",value,")");
Atomics.store(state.sabOPView, state.rcIds[opName], value);
Atomics.notify(state.sabOPView, state.rcIds[opName]);
log(opName+"() => notify(",state.opIds.rc,",",value,")");
Atomics.store(state.sabOPView, state.opIds.rc, value);
Atomics.notify(state.sabOPView, state.opIds.rc);
};
/**
@ -460,17 +460,19 @@ const initS11n = ()=>{
const waitLoop = async function f(){
const opHandlers = Object.create(null);
for(let k of Object.keys(state.rcIds)){
for(let k of Object.keys(state.opIds)){
const vi = vfsAsyncImpls[k];
if(!vi) continue;
const o = Object.create(null);
opHandlers[state.opIds[k]] = o;
o.key = k;
o.f = vfsAsyncImpls[k];// || toss("No vfsAsyncImpls[",k,"]");
o.f = vi;// || toss("No vfsAsyncImpls[",k,"]");
}
let metricsTimer = self.location.port>=1024 ? performance.now() : 0;
// ^^^ in dev environment, dump out these metrics one time after a delay.
while(true){
try {
if('timed-out'===Atomics.wait(state.sabOPView, state.opIds.whichOp, 0, 150)){
if('timed-out'===Atomics.wait(state.sabOPView, state.opIds.whichOp, 0, 500)){
continue;
}
const opId = Atomics.load(state.sabOPView, state.opIds.whichOp);
@ -513,7 +515,6 @@ navigator.storage.getDirectory().then(function(d){
state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize);
state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize);
state.opIds = opt.opIds;
state.rcIds = opt.rcIds;
state.sq3Codes = opt.sq3Codes;
Object.keys(vfsAsyncImpls).forEach((k)=>{
if(!Number.isFinite(state.opIds[k])){

View File

@ -1,5 +1,5 @@
C An\salternative\smessaging\sstrategy\sfor\sthe\sOPFS\sVFS\sproxy\swhich\suses\sonly\sSharedArrayBuffer\sand\sAtomics,\sinstead\sof\sworker\smessages,\sfor\scommunication\s(only\sthe\sinitial\sone-time\shandshake\sduring\sinitialization\suses\sworker\smessages).\sIt\sruns\sspeedtest1\sapprox.\s15-20%\sfaster\sbut\sstill\s20-ish%\sslower\sthan\sWASMFS.
D 2022-09-20T08:27:57.073
C Remove\sextraneous\sresult-code\sSAB\sslots.\sDoc\sadditions.
D 2022-09-20T10:11:52.007
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -474,7 +474,7 @@ F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle a004bd5eeeda6d3b28d16779b7f1a80305bfe009dfc7f0721b042967f0d39d02
F ext/wasm/GNUmakefile b65cd280059febd4f034b856139fde52f7edb7326133f7e0588b8efcf396709c
F ext/wasm/GNUmakefile 5b848d4d20c31b2aac3dcfabaf5deaf56fe9db9ca1299a4dede1bcd27821426b
F ext/wasm/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 150a793a47205b8009ac934f3b6d6ebf67b965c072339aaa25ce808a19e116cc
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
@ -484,7 +484,7 @@ F ext/wasm/api/post-js-header.js 0e853b78db83cb1c06b01663549e0e8b4f377f12f5a2d9a
F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77
F ext/wasm/api/sqlite3-api-glue.js 366d580c8e5bf7fcf4c6dee6f646c31f5549bd417ea03a59a0acca00e8ecce30
F ext/wasm/api/sqlite3-api-oo1.js 2d13dddf0d2b4168a9249f124134d37924331e5b55e05dba18b6d661fbeefe48
F ext/wasm/api/sqlite3-api-opfs.js 1df64b2a11b7f71ba5c7a5807b4d62727e2c712e537eb563caedc67c5a38d149
F ext/wasm/api/sqlite3-api-opfs.js 8611680362619cac2425fd77fa9bff00690c80a17a6b95cdd1a39c2cc33e11d0
F ext/wasm/api/sqlite3-api-prologue.js 0d2639387b94c30f492d4aea6e44fb7b16720808678464559458fd2ae3759655
F ext/wasm/api/sqlite3-api-worker1.js ee4cf149cbacb63d06b536674f822aa5088b7e022cdffc69f1f36cebe2f9fea0
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
@ -519,7 +519,7 @@ F ext/wasm/speedtest1.html 512addeb3c27c94901178b7bcbde83a6f95c093f9ebe16a2959a0
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
F ext/wasm/sqlite3-opfs-async-proxy.js 038ecd8558abc3f46cfedd560093fef4d460af8c0d0009ab84f2abdc10916a6a
F ext/wasm/sqlite3-opfs-async-proxy.js e3c5e1b6416e9c08c713c43fa98319b06fac622ecb813f294b047072b089fba6
F ext/wasm/sqlite3-worker1-promiser.js 4fd0465688a28a75f1d4ee4406540ba494f49844e3cad0670d0437a001943365
F ext/wasm/sqlite3-worker1.js 0c1e7626304543969c3846573e080c082bf43bcaa47e87d416458af84f340a9e
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
@ -2026,11 +2026,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 5ca412ced24b4e3af5f467e710a597ed440badf7b8335346aade11d3cad3d1a1
R eef8f82c266e71b1fc83e097c56f095e
T *branch * opfs-proxy-atomics
T *sym-opfs-proxy-atomics *
T -sym-fiddle-opfs * Cancelled\sby\sbranch.
P a83ee3082d89439ea3ad5737e63e25bebb0f91895aca006ce5fecf5b93a2651a
R bb080f9a3495e6fa47cacc332af06e26
U stephan
Z 1c049de5a4413363c0d5cd656309295d
Z e5fc885edbb6664192b4f06eefccf3e5
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
a83ee3082d89439ea3ad5737e63e25bebb0f91895aca006ce5fecf5b93a2651a
88de20712bbe3e11ea74af95edc34e9ab9f346f9aa0a30931e5a9e1f96ce57b0