-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[HIGH] Add SQLite support to web browser and fallback to IndexedDB #34289
Comments
Below is the way to check if the browser supports SQL Lite or IndexedDB then we can perform the appropriate operations like storing and retrieving data from either SQL Lite or IndexedDB.
|
Hey @MIAhmed! What's your Slack handle? Would you be interested in creating a proposal for this? |
Thanks for running with this @muttmuure, I think generally there was consensus that this is a good idea, but let me post a formal proposal first just to get everyone on board. Going to slap a planning label on this and put it on HOLD |
Triggered auto assignment to @lschurr ( |
Chatting in this thread |
Does this still rely on the deprecated WebSQL standard? As far as I'm aware only WASM is now a viable option to use SQL on this platform. |
|
No, I'm referring to the official SQLite wasm build |
Sounds like we got consensus to do some exploratory research here and investigate the potential performance benefits. |
For transparency to our open-source community, we've asked Margelo to begin researching this since they're experienced with working in Onyx and maintain https://github.com/Margelo/react-native-quick-sqlite |
commenting here for assignment! @roryabraham |
@chrispader having set up wasm support for Encryptify, I wonder if this is something we can implement at the react-native-quick-sqlite layer? That way, we would be able to leave Onyx mostly unchanged – just check if OPFS is supported, and if it is use the existing quick-sqlite storage provider, if not fall back on IndexedDB. We could also create a log of grafana graph to see how much the IndexedDB provider is actually used in the wild. That way a year from now there's no guesswork – we can look at how much it's actually used by users and consider dropping it from Onyx to simplify the codebase. |
I did some research today and here's are my initial thoughts: cc @roryabraham @muttmuure @adhorodyski (Lmk if you have any comments/critic) Which SQLite + WASM approach to takeAs suggested in the documentation of the official library (SQLite WASM) i would go for the approach where we use the extra wrapped worker thread. This way, additionally to (potentially) improved speed we have the benefit of offloading much of the load in Onyx to a different thread. Reference: Worker + Promise approach
I would definitely add this functionality to Onyx integration
Exactly! As you've suggested, we would then check for availability of OPFS in Onyx and use Onyx operates async anyways, so this approach wouldn't require any changes in the library. Relational data approach / Onyx re-design?From https://expensify.slack.com/archives/C05LX9D6E07/p1704972138886149?thread_ts=1704921473.038539&cid=C05LX9D6E07 by @adhorodyski
I'm not sure if i understood your idea 100%, but if it refers to re-designing Onyx to support relational data, i don't think that would be a good idea atm. I wouldn't suggest to rely on any specific storage provider implementation too much, like SQLite on both web and native. Or was the idea to drop Onyx and create a completely re-designed (relational data) storage solution? I like the idea of improving the overall performance by not trying to convert relational data into key-value data and therefore losing potential of indexing and efficient querying. I just think it wouldn't be a good idea to try achieve this in Onyx... Imo Onyx is exclusively designed as a key-value store and its big advantage is that it's not dependent on any specific storage layer, instead it can use any underlying storage solution... and we will potentially improve this aspect even more. I also agree with @tgolen, that as long as we don't completely re-structure our approach to querying and persisting data, i don't think we need (Correct me if i got any aspect of your suggestion wrong though) PerformanceAs @roryabraham already mentioned in this Slack thread the main benefit would definitely be faster speeds and to offload a lot of work to a separate worker thread and therefore unblock the main thread and improve app's performance. I haven't created any real benchmarks and performance comparisons with IndexedDB yet, but from what i've read it's definitely faster than (Asking about what to do next in "Going forward...") Analytics
That definitely makes sense! Do we already use Grafana and is there an account/token i can use? I could also imagine adding analytics for web and native performance of SQLite. This way we could analyze which kind of devices profit the most from this change and which might have problems. Going forward...@roryabraham @tgolen just to make sure i'm not putting too much work into this straight ahead.. Was the idea to create a P/S for this with all the actual problems solved in the app first? Or do we want to dive straight into the actual implementation in Also, do we want to create performance benchmarks before or after the actual implementation in the library? |
That's really anyone's guess and mine would be mere speculation. That will, at least in part, depend on whether those objects span db pages, because...
Faster compared to (say) postMessage() because it eliminates an extra copy which might otherwise be necessary1. For example, when the library reads from storage, it passes a destination byte array to the VFS. In this particular case, the library and the VFS-related I/O live in different threads but they communicate via the same SharedArrayBuffer, so the I/O itself is performed directly on that shared buffer. The coordination/synchronization of the communication between those two threads, irrespective of the actual I/O, is where the biggest single performance hit comes from. The process goes something like:
The same happens for writing: the library thread populates the SAB, tells the I/O thread that data is available, and then waits on the I/O thread's response to that write. Thanks to the SAB, the I/O thread does not need to make a separate copy of that data before passing it on to the OPFS layer. Does that answer your question? Footnotes
|
Yes, thank you 🙏 We've investigated We also looked at the performance when we have no serialisation/deserialisation on the worker thread API, but assuming that all the data layer code would operate in the worker thread directly (ie. API calls happening there and
I. e. if there is no communication between threads, then Let me know what do you about the results and further direction 😊 |
AFAIK there is no more optimal approach for general-purpose or high-level software. We internally use a fit-to-purpose serialization approach which has proven to be faster, but it's in no way flexible. It depends, for example, on having a fixed number of fixed-size values, which isn't practical for anything but the most specialized of use cases.
Unfortunately, my lack of background with your apps, infrastructure, and use cases leaves me unable to say terribly much which is likely to be of use. If you like, we can do a video call and, with some hand-holding from you, perhaps i'll be able to offer some concrete suggestions and/or provide guidance on getting the most out of sqlite's JS/WASM APIs. Just send a meeting link and time to support at sqlite org and i can make the time slot work. |
@sgbeal I sent an invitation to your email (took it from github profile, sorry, didn't find your contact on support page) |
Got it. See you on Friday! |
We had a meeting with @sgbeal, key notes are:
After a discussion some options with @sgbeal we came to next conclusions:
|
To clarify: that capability is currently hypothetical. The new Chrome feature might allow us to add concurrency to that VFS, but we won't know for sure until we're able to experiment with it. Even if we do that, however, that OPFS feature is experimental and currently only in Chrome, so it may still change in incompatible ways. We have no information about whether the other browsers plan to adopt that feature and we are not keen on the idea of releasing a Chrome-only VFS. |
most recent discussion here |
conversation is ongoing, with some recent highlights being:
excited to hear more about @adhorodyski's proposal. |
I’ve been deeply invested in ongoing discussions about performance and have observed that our primary challenge doesn't seem to stem from the storage database itself but rather from extensive processing times on the main thread. This challenge manifests in two main areas:
It’s clear these issues are significant and not directly related to the choice of storage provider. I’m curious about the native side - do we face similar challenges there, or is the conversation about moving storage handling off the main thread mainly focused on web implementations? Given my history with Onyx, I have immense respect for what we've built and its evolution from a simple pub-sub model to a sophisticated key/value storage solution. As we navigate these performance challenges, I believe it's beneficial to revisit the foundational goals of Onyx:
Reflections on Onyx’s Purpose:
Considering Alternatives:
I once hesitated to use Redux, favoring more familiar patterns like MVC with MobX. Yet, the potential for integrating existing solutions through middleware, possibly enhancing Onyx or even adopting new approaches, is worth considering. This doesn’t diminish Onyx’s value but opens a dialogue on leveraging collective wisdom and advancements from the wider community. As we ponder the future of Onyx, I see an opportunity for evolution rather than abandonment. Could we envision a redesign or integration that honors Onyx's original principles while addressing our current challenges? I’m eager to contribute to a path forward that builds on our collective achievements and addresses the needs of our evolving technology landscape. |
I have deeply appreciated all your work on Onyx over the years! Your expertise and opinions are super gracious and encouraging. I'll respond to a few points here and give some general opinions of mine.
I think we did a pretty good job of delivering those things.
Yes, I explored that heavily. I have used Redux in other projects, so I was pretty familiar with it. I found that the excessive boilerplate was just too much to deal with in a huge project. I also explored alt in a desire to see if a flux pattern with less boilerplate would help. I built the K2 extension with
The off-thread conversation has been focused on web implementations. That's not to say that the native side is perfect, but it seems like the web side is where most people have focused on performance. I don't know if there is a correlation there or if it's just natural tendencies.
Yeah, I am totally down for this. I think of the |
An interesting library we could consider (or pull from for inspiration) is @legendapp/state. Reviewing the design goals for Onyx written by @tgolen, and adding this one:
legend-state seems to check all the boxes. I believe it's quite similar to Onyx in its design, with even less boilerplate. I also think it would be feasible to leverage it to simplify Onyx internals while keeping the existing interface for Onyx largely unchanged, avoiding the need for a major app-wide refactoring effort. I've also met the maintainer in person a few times at React Native conferences, and I believe he'd be open to working with us. A direct line to support could alleviate concerns with lack of control over the library. |
@roryabraham I'm going to need some more time to prepare a draft of how I think this could look like, but to give you all more context I genuinely think nearly all we need is the right design and composition of some primitives, not much of the new tools - this might be the 10% but mostly due to the ergonomics of not rewriting community libraries. I basically work with SQL queries & JS Promises, binding them to the UI. I'll do my best to share a WIP proposal of this design next week. |
It seems like conversation has stalled for the last few weeks, and the initial investigations we did have prettymuch concluded. It sounds like @adhorodyski has an idea he'd like to propose for which SQLite on the web would be a prerequisite, so I'm going to assign this issue to him. I'm also going to unassign @hannojg and @kirillzyusko because their explorations are complete. |
@roryabraham still working on it - correct with the web support being a prerequisite, but after a few discussions with @jbroma together we decided to slightly pivot as IndexedDB is for now the only option which fully supports this platform. I'm aiming for a design where once web catches up, we can easily migrate just this very piece with a very little effort. Will update within days! |
Hey @adhorodyski, we discussed this internally, and since we're not working from a clear problem statement here and the ROI of any changes is still very much up-in-the-air, we've agreed that we're going to close this issue for now. We advise that you shift your focus into other areas of the performance audit for the time being. We love SQLite and may want to pick this discussion back up someday, but for now we're going to cap it here for #focus. Thanks everyone for all your participation so far! |
@roryabraham I agree this was fine to be closed - I'll post my research on Slack just so we don't loose it later on (I learned a lot on the integrations for SQLite/IndexedDB), I think this is still valuable and holds/maybe we'll continue the discussion from there/kill it with fire for now :D |
cc @roryabraham posted internally under this thread, please let me know if there's a better place for this :) |
thanks, I think that's an appropriate place for that |
Placeholder tracking issue for adding SQLite support to Chrome, Safari, Edge and FireFox (Not IE)
Also for adding a fallback mechanism to retrieve data from IndexedDB when SQLite fails or has a problem
cc @roryabraham
The text was updated successfully, but these errors were encountered: