1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

OPFS async proxy: add a wait-and-retry policy to the get-sync-handle step to help account for cross-tab locking.

FossilOrigin-Name: 45c48c63d311052105d102189208495b2b53fa3c4174884ecf63b757aa4016e5
This commit is contained in:
stephan
2022-10-04 09:12:05 +00:00
parent f6b6188bdd
commit c7fb48d4b6
4 changed files with 63 additions and 27 deletions

View File

@ -915,9 +915,19 @@ const installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri){
opfsUtil.OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype); opfsUtil.OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype);
sqlite3.oo1.dbCtorHelper.setVfsPostOpenSql( sqlite3.oo1.dbCtorHelper.setVfsPostOpenSql(
opfsVfs.pointer, opfsVfs.pointer,
[
/* Truncate journal mode is faster than delete or wal for /* Truncate journal mode is faster than delete or wal for
OPFS, per speedtest1. */ this vfs, per speedtest1. */
"pragma journal_mode=truncate" "pragma journal_mode=truncate;",
/*
This vfs benefits hugely from cache on moderate/large
speedtest1 --size 50 and --size 100 workloads. We currently
rely on setting a non-default cache size when building
sqlite3.wasm. If that policy changes, the cache can
be set here.
*/
//"pragma cache_size=-8388608;"
].join('')
); );
} }

View File

@ -144,13 +144,38 @@ const getDirForFilename = async function f(absFilename, createDirs = false){
handle object (which must be a valid handle object), lazily opening handle object (which must be a valid handle object), lazily opening
it if needed. Timestamps the handle for use in relinquishing it it if needed. Timestamps the handle for use in relinquishing it
during idle time. during idle time.
In order to help alleviate cross-tab contention for a dabase,
if an exception is thrown while acquiring the handle, this routine
will wait briefly and try again, up to 3 times. If acquisition
still fails at that point it will give up and propagate the
exception.
*/ */
const getSyncHandle = async (fh)=>{ const getSyncHandle = async (fh)=>{
if(!fh.syncHandle){ if(!fh.syncHandle){
//const t = performance.now(); const t = performance.now();
//warn("Creating sync handle for",fh.filenameAbs); log("Acquiring sync handle for",fh.filenameAbs);
const maxTries = 3;
let i = 1, ms = 300;
for(; true; ms *= ++i){
try {
//if(1===i) toss("Just testing.");
//TODO? A config option which tells it to throw here
//randomly every now and then.
fh.syncHandle = await fh.fileHandle.createSyncAccessHandle(); fh.syncHandle = await fh.fileHandle.createSyncAccessHandle();
//warn("Got sync handle for",fh.filenameAbs,'in',performance.now() - t,'ms'); break;
}catch(e){
if(i === maxTries){
toss("Error getting sync handle.",maxTries,
"attempts failed. ",fh.filenameAbs, ":", e.message);
throw e;
}
error("Error getting sync handle. Waiting",ms,
"ms and trying again.",fh.filenameAbs,e);
Atomics.wait(state.sabOPView, state.opIds.xSleep, 0, ms);
}
}
log("Got sync handle for",fh.filenameAbs,'in',performance.now() - t,'ms');
} }
fh.syncHandleTime = performance.now(); fh.syncHandleTime = performance.now();
return fh.syncHandle; return fh.syncHandle;
@ -589,23 +614,24 @@ const waitLoop = async function f(){
} }
/** /**
waitTime is how long (ms) to wait for each Atomics.wait(). waitTime is how long (ms) to wait for each Atomics.wait().
We need to wait up periodically to give the thread a chance We need to wake up periodically to give the thread a chance
to do other things. to do other things.
*/ */
const waitTime = 250; const waitTime = 200;
/** /**
relinquishTime defines the_approximate_ number of ms relinquishTime defines the_approximate_ number of ms after which
after which a db sync access handle will be relinquished a db sync access handle will be relinquished so that we do not
so that we do not hold a persistent lock on it. When the following loop hold a persistent lock on it. When the following loop times out
times out while waiting, every (approximate) increment of this while waiting, every (approximate) increment of this value it
value it will relinquish any db handles which have been idle for will relinquish any db handles which have been idle for at least
at least this much time. this much time.
Reaquisition of a sync handle seems to take an average of Reaquisition of a sync handle seems to take an average of
0.6-0.9ms on this dev machine but takes anywhere from 1-3ms 0.6-0.9ms on this dev machine but takes anywhere from 1-3ms every
every once in a while (maybe 1 time in 5 or 10). once in a while (maybe 1 time in 5 or 10). Outliers as long as
7ms have been witnessed, but they're rare.
*/ */
const relinquishTime = 1000; const relinquishTime = 750;
let lastOpTime = performance.now(); let lastOpTime = performance.now();
let now; let now;
while(!flagAsyncShutdown){ while(!flagAsyncShutdown){
@ -619,7 +645,7 @@ const waitLoop = async function f(){
if(fh.syncHandle && ( if(fh.syncHandle && (
now - relinquishTime >= fh.syncHandleTime now - relinquishTime >= fh.syncHandleTime
)){ )){
//warn("Relinquishing for timeout:",fh.filenameAbs); log("Relinquishing for timeout:",fh.filenameAbs);
await closeSyncHandle(fh) await closeSyncHandle(fh)
/* Testing shows that we have to wait on this async /* Testing shows that we have to wait on this async
op to finish, else we might try to re-open it op to finish, else we might try to re-open it

View File

@ -1,5 +1,5 @@
C Update\sthe\s'start\sin\sspeedtest\skvvfs'\slink\sin\sspeedtest1-worker\sto\saccount\sfor\srecent\schanges. C OPFS\sasync\sproxy:\sadd\sa\swait-and-retry\spolicy\sto\sthe\sget-sync-handle\sstep\sto\shelp\saccount\sfor\scross-tab\slocking.
D 2022-10-04T08:58:22.077 D 2022-10-04T09:12:05.870
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -487,7 +487,7 @@ F ext/wasm/api/pre-js.js 2db711eb637991b383fc6b5c0f3df65ec48a7201e5730e304beba8d
F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb48c8bc4bbd463f05b021a99 F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb48c8bc4bbd463f05b021a99
F ext/wasm/api/sqlite3-api-glue.js a5a1bd620e2e2c26b6e843cf439548b35c5bb5ed21b24b89a412e0b0a8592c42 F ext/wasm/api/sqlite3-api-glue.js a5a1bd620e2e2c26b6e843cf439548b35c5bb5ed21b24b89a412e0b0a8592c42
F ext/wasm/api/sqlite3-api-oo1.js ac1e08d36bdfb5aa0a2d75b7d4c892fd51819d34c932370c3282810672bcc086 F ext/wasm/api/sqlite3-api-oo1.js ac1e08d36bdfb5aa0a2d75b7d4c892fd51819d34c932370c3282810672bcc086
F ext/wasm/api/sqlite3-api-opfs.js d82870cffef9eef6511c650759c3798b59f10c8338587789abd84be2d9d845c3 F ext/wasm/api/sqlite3-api-opfs.js 8727adb9d69758c8c1adfc68b5445138b2e48da3a44ab5e67e4e13a7668c582f
F ext/wasm/api/sqlite3-api-prologue.js baf88cf253a35153674b068b5125238993ea2a7804152d238b5e40140b506ef5 F ext/wasm/api/sqlite3-api-prologue.js baf88cf253a35153674b068b5125238993ea2a7804152d238b5e40140b506ef5
F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8 F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
@ -522,7 +522,7 @@ F ext/wasm/speedtest1.html e4cb5d722b494104fc1249e7c008ca018f820a784833c51004c95
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0 F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5 F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
F ext/wasm/sqlite3-opfs-async-proxy.js 3f8086e543a576a556c17f8ee7c75009fb8e2d3f9bbb9c0de6b9c285dd7f5634 F ext/wasm/sqlite3-opfs-async-proxy.js 6c96f9598a251a44b3ff435cab85ba74b199a7d35f0d50c64625f2e3deb199db
F ext/wasm/sqlite3-worker1-promiser.js 307d7837420ca6a9d3780dfc81194f1c0715637e6d9540e935514086b96913d8 F ext/wasm/sqlite3-worker1-promiser.js 307d7837420ca6a9d3780dfc81194f1c0715637e6d9540e935514086b96913d8
F ext/wasm/sqlite3-worker1.js 466e9bd39409ab03f3e00999887aaffc11e95b416e2689596e3d7f1516673fdf F ext/wasm/sqlite3-worker1.js 466e9bd39409ab03f3e00999887aaffc11e95b416e2689596e3d7f1516673fdf
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5 F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
@ -2029,8 +2029,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 6b4fb7c4e399ecc948ad41f5fa3139a9293cc822cd7efa2b83dc5fb1660b3ec6 P f4d5ba412e0c1a031430a32c9ed1e11a09af33f9883150e660cc05e49fe56e6a
R 0b82b28db72e951b49c91c31da521211 R ef7e5c2872567f2db1aff569fb1ba87c
U stephan U stephan
Z c1a19f484dc6300f67e1f220bff1c32f Z adf5485abd70bc27cf1b4b2e2c0adea5
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
f4d5ba412e0c1a031430a32c9ed1e11a09af33f9883150e660cc05e49fe56e6a 45c48c63d311052105d102189208495b2b53fa3c4174884ecf63b757aa4016e5