SQLite 3.40 to support browser API, including OPFS #63
Replies: 5 comments 16 replies
-
(Speaking as the developer of the new sqlite subproject...) COOP/COEP is a huge nuisance but we currently have no alternative for OPFS except using Asyncify. The sqlite project is made up of long-time C programmers, none of whom are big fans of huge JS build tools. We'd prefer to "keep it simple," and all of the current code, minus the glue code from Emscripten, is hand-written by us with no magic involved. We're not keen on using magic tools like Asyncify because, essentially, when they break there is no fixing them. We don't want to tie ourselves to that, and have made every effort to avoid dependencies where at all possible (noting that certain Emscripten dependencies are, at the lowest levels, unavoidable). For those with more modest persistence needs, localStorage and sessionStorage can be used without COOP/COEP, but are limited to main-thread use.
Our benchmarks were unfortunately not well-documented. Until just recently we benchmarked continually against the Emscripten WASMFS's OPFS support, and finally (with much tuning) got ours to a competitive point with that one, more or less neck and neck with no consistent winner in terms of overall performance. Their impl. also requires SAB/Atomics. We also compared, though less intensively, against WebSQL, again with no clear all-around winner - it really depends on the workload. One of my mid-term goals is to create a benchmarking page very much like the one you've done for your various backends. Until then, we've used sqlite's age-old benchmarking app, speedtest1, for most benchmarking and are quite pleased with the overall performance. |
Beta Was this translation helpful? Give feedback.
-
I have not seen this, and no one has (yet) reported corruption with wa-sqlite IndexedDB classes (and people are using it with multiple tabs). Assuming your code is correct, this would indicate your browser did not properly implement the IndexedDB spec. How were you handling locking? If you were relying on IndexedDB's locks then I can understand how that could happen because I have made my own mistakes with them. I implement SQLite locking (i.e. xLock and xUnlock) with the WebLocks API. For example, absurd-sql depends on IndexedDB locks for SQLite locking, but its implementation has at least one problem in that it doesn't match SQLite's locking model which might explain why it also has corruption issues with multiple tabs. I'm not saying that you should be using IndexedDB over OPFS - IndexedDB can be a pain. I just think your reason to rule it out completely seems like a bug, either in your code or your browser, which could be fixed. |
Beta Was this translation helpful? Give feedback.
-
A big assumption :). It was literally our first-ever, and only-ever, IDB code. We weren't terribly excited about using it, partly because...
it has a poor reputation for cross-browser incompatibilities. We didn't do more than very cursory toying with it. Spending time working around browser-specific issues, especially for browsers i won't use for reasons of principle (but whose users are always the first to cry "it doesn't work on my iDevice!"), is not a way i intend to spend my coding time nowadays.
We didn't, IIRC, do any explicit locking, but i don't think that experiment ever even got checked in, so i can't go verify that. WebLocks are still an experimental tech, which takes it off of our radar completely. We're far more interested in using techs which are currently widely deployed and cross-browser. OPFS has been the one exception to that guiding principle.
That's a fair assessment, but we were never excited about IDB in the first place. Our whole wasm effort was literally triggered by one single catalyst: OPFS. Any other browser-side persistence we manage to get is just bonus points. We're not actively looking to extend our persistence catalog, nor to spend any development effort on IDB support. The idea of storing an sqlite db in an IDB which itself is very likely backed by sqlite kinda makes me queasy. |
Beta Was this translation helpful? Give feedback.
-
I've spent the last few days making some performance comparisons to weigh up the benefit of converting an existing application from IndexedDB to WASM SQLite. The application is a dictionary tool that downloads all the data on startup (100,000s of writes) and then needs to do lookups on words, often prefix lookups. In particular, I'd really like to improve the initial insert performance. I have the comparison here: https://wasm-sqlite-test.netlify.app/ (source code) In summary, I found that both insert and query performance improved with the official SQLite WASM build using the OPFS SyncAccessHandle VFS, but the insert performance improvement was much better when using On Chrome the following results are pretty typical for me (and Firefox and Safari are similar): I'd prefer to stick with the official SQLite WASM build but That said, I'm completely new to SQLite so it's quite possible I'm just holding it wrong! |
Beta Was this translation helpful? Give feedback.
-
For many of mine, simply impossible. So I chop the 200MB+ file into 10MB blocks and then put them together on the other side. I don't currently have storage for the blocks so you can resume downloading in a separate session, but I did when I was using JSON. With IDB you can't have any That said, for those users, insert time is probably going to be an order of magnitude less important than download time anyway... But there is nothing stopping you from first downloading all the blocks, then importing in one go. |
Beta Was this translation helpful? Give feedback.
-
In case you didn't see it in the OPFS discussion, the next SQLite non-patch release will contain a browser implementation, and that will include an Origin Private File System VFS for persistent storage. That's great news for everyone!
Assuming this new API works well, what does that mean for wa-sqlite? If you want to use wa-sqlite solely for a persistent SQL database (and not, say, to write your own storage extensions), then the answer depends on whether you prefer the limitations of Asyncify to the limitations of SharedArrayBuffer and OPFS.
There are currently two implementation approaches for connecting SQLite's synchronous file system operations to a browser's asynchronous storage: Asyncify (used by wa-sqlite), and SharedArrayBuffer (used by the official SQLite OPFS VFS). Choosing Asyncify makes the WASM bigger and slower, while choosing SharedArrayBuffer adds requirements on where and how web assets are served and OPFS is not yet supported on Firefox (though the tracking bug activity looks very promising).
If you can live with SharedArrayBuffer's COOP/COEP restrictions and OPFS browser support, I would recommend the official SQLite implementation for its official support, complete API, legendary test coverage, and permissive license (actually it doesn't require a license at all). Otherwise, if COOP/COEP is burdensome, you can't wait for Firefox, or you have custom storage ideas (including for virtual tables), wa-sqlite will still be here.
I am curious to see how the official OPFS VFS performance will compare to the wa-sqlite IDBBatchAtomic VFS. In my comparisons of OPFS vs IndexedDB (both in wa-sqlite), the ability to use batch atomic writes made transactions significantly faster. That might be enough to make up for (or exceed) the Asyncify performance penalty, depending on the workload of course. I would love to see someone create a batch atomic IndexedDB VFS using SharedArrayBuffer - that might be the fastest of all.
Beta Was this translation helpful? Give feedback.
All reactions