Live data from Hacker News

How we sped up Notion in the browser with WASM SQLite

notion.so

61–70 of 107 posts

Re: How we sped up Notion in the browser with WASM SQLite

#61

Earlier quoted context omitted.

If you think those read speeds are great, try DuckDB (which has many SIMD improvements) if you want to blow your socks off.

Isn’t one OLTP and the other OLAP? I don’t understand why DuckDB is often suggested as a drop-in replacement.

Yes, DuckDB is OLAP, SQLite is OLTP. I should have called that out.

But if you are doing aggregate or skip-scan analysis and if they're talking about read speeds and in-memory processing, well, SQLite leaves some performance on the table by being single-threaded, as far as I can tell.

Re: How we sped up Notion in the browser with WASM SQLite

#62

Earlier quoted context omitted.

> Meanwhile in AWS you would pay $27k a month to have the same IOPS as a Lenovo Thinkpad X1. This is kind of an unfair comparison. Essentially nobody needs a million iops for their database. Even an extremely busy database doesn't need to scan all of the data it holds (or at least, if it does, you're using it very wrong—that's why we have indexes). A fast disk is possible on a laptop because it's a tiny hop to RAM. A…

"Nobody needs IOPS until they need IOPS" I've had to scrub a multi terabyte database of PII before moving to a staging environment, it hurts. With modern data architectures, you may write the same data 4-5 times in its life cycle, staging data, data warehouses, marketing, PowerBI, Looker, etc... Especially reporting solutions, where they may aggregate massive amounts of data and write it to temp tables. It will requi…

I don't know about your specific example, but doing an operation where you rewrite most of a multi terabyte database online is almost certainly not best accomplished with SELECT/UPDATE. Even if you need multiple passes, that's N terabytes times M passes times two. That's... not a lot of reads and writes. Dumping the database to files on blob storage, rewriting them, then reading them into your destination is almost certainly the fastest and cheapest way to go about that.

And that's not an iops avoidance thing, that's a "this isn't what your database is built to do with the configuration your running it in" sort of thing.

Re: How we sped up Notion in the browser with WASM SQLite

#63
We've been using wasm sqlite with kotlin-js and the kotlin sqldelight framework. This is admittedly a bit of an exotic stack to be running in a browser. But it actually works surprisingly well. Unfortunately the failure modes with opfs are kind of ugly and need some attention. A key issue is controlling what happens when you have multiple tabs open interacting with the same DB.

One interesting thing is that opfs maximum disk usage is kind of browser specific but tends to be a percentage of the available diskspace measured in GB rather than some lowish number like 5MB as is typical for e.g. browser local storage. This makes it suitable for locally caching and syncing large amounts of remote database content.

We've had a few challenges with opfs and particularly limited support for this on Safari it kind of works but with some caveats. Chrome/Firefox are fine. Our web app is packaged up as a PWA for use on mobile.

Another issue is that opfs creates issues with loading resources from external websites. E.g. we have HTML previews that may include images on external domains that the browser will render fine without opfs enabled but will refuse to render when using opfs, unless you set crossOrigin=anonymous on the img tag.

Relative to indexed-db, which is supported by most browsers, you gain a more sane API to access data and more flexible querying and support for things like joins. I've had some exposure to indexed-db and IMHO it's a case study in bad API design gone horribly wrong. Querying is very limited and the APIs are poorly documented and have weird failure modes. Sqlite is an absolute pleasure to use in comparison and probably faster and way more capable.

Re: How we sped up Notion in the browser with WASM SQLite

#64
post #50
post #20

Seeing things like that excite me a lot, I can't wait for a future where all the code is written in whatever language you like and runs through WASM in the browser. The HTML and JS can go back doing that thing they are built for: Displaying the UI and handling the interactions.

displaying ui and handling interactions ends up being most of the app though

Not necessarily. It's just that a lot of SPAs don't contain a lot of business logic because it's too tedious to do without a client side database; which means you end up offloading a lot of business logic to server side databases behind some kind of API.

Adding local persistence in the form of an actual database, allows you to do more of these things client side. Which means you end up with more business logic that you can cleanly separate from your data rendering logic and other cruft needed for e.g. form filling, data validation, and what not. You still need that of course but it makes web applications more similar to full desktop applications in the sense that the server might be a lot lighter or even be optional (other than serving the code and other assets).

I've actually been toying with building a Google Reader style application that stores its data in the browser recently. I use a few minimal server scripts to work around cors issues for fetching feeds and html previews. But aside from that, there is no need for a server. I can save local state (stored in indexdb) to a file and download it and then restore it from the same file as a backup strategy.

I've been adding search capabilities with tf/idf ranking, phrase matching. I'm using OpenAI to help summarize and tag content. And I'm currently adding a light weight vector search implementation. This is all running in the browser (except for openAI).

My goal with this is experimenting with RAG against news content. So, I've been piecing together things I need for this and raising the ambition level as I've progressed in the last few weeks. Most of this is probably not optimal and a big motivation for me is to just wrap my head around all the bits and pieces I need. But there's no good reason why most of those things could not be optimized with e.g. some wasm code that uses web-gpu for doing math and less memory intensive ways of storing stuff.

BTW, I'm using kotlin-js and kotlin-multiplatform which makes it easy to forget that I'm dealing with Javascript and very limited browser APIs under the hood. UI is still tedious to do but I have a growing amount of code that is pure business logic, algorithms, or other stuff you'd normally run on a server and implement in a language like Kotlin. Which is why it's nice to be using that in the browser.

Re: How we sped up Notion in the browser with WASM SQLite

#65
post #36

Notion takes 15s to load to an empty page. Then another 5 to dismiss the popup about new AI features and the like. I'm glad they are making their app faster, in the meantime I (browser user) have cancelled my team's subscription and will be using something else.

Stay away from Clickup, it's just as slow if not worse. Also same AI notices.

Re: How we sped up Notion in the browser with WASM SQLite

#66
This is both silly and somewhat off-topic, but on the subject of doing database work on the client side ... has anyone experimented with using non-rendered DOM as 'table' and CSS selectors as 'query language'?

I'm not talking about 'using the DOM to store data' in the traditional sense. The idea is rather (roughly) to store each database 'table' as a child of a hidden DocumentFragment, with 'rows' as its children, etc. Then we'd query this data using CSS selectors (or XPath).

For example, instead of

  SELECT * FROM Employees WHERE gender = 'male' AND age > 30
you'd have something like:

  customersTbl.querySelectorAll('row:has(cell-gender[value="male"]):has(cell-age[value > "30"])')
And instead of

  SELECT * FROM Employees WHERE gender = 'male' OR age > 30
you'd have something like:

  employeesTbl.querySelectorAll('row:has(cell-gender[value="male"], cell-age[value > "30"])')
You can even have (truly) structured cells! Instead of

  SELECT * FROM Employees WHERE name->>'first_name' = 'John'
you can have:

  employeesTbl.querySelectorAll('row:has(cell-name:has(cell-first_name[value="John"]))')
And for querying array-like structures, instead of:

  SELECT * FROM employees WHERE skills::jsonb ? 'JavaScript';
you can have:

  employeesTbl.querySelectorAll('row:has(cell-skills > cell-skill[value="JavaScript"])')
I can certainly imagine the performance to be horrible, but having never tried out the idea (and having too meager a mental model of DOM performance to reason from) I can also imagine it being surprisingly decent for smaller datasets. Who knows? :-)

Edit: silly me indeed to think CSS attribute selectors already can do numeric comparisons! See here: https://github.com/w3c/csswg-drafts/issues/354

Re: How we sped up Notion in the browser with WASM SQLite

#67
post #36

Notion takes 15s to load to an empty page. Then another 5 to dismiss the popup about new AI features and the like. I'm glad they are making their app faster, in the meantime I (browser user) have cancelled my team's subscription and will be using something else.

Curious where you're moving? About to begin finding a tool similar to Notion (but not Notion).

Someone posted recently on the golang subreddit that they are building a collaboration tool with performance being the priority: https://www.superthread.com/

I am not affiliated with them and haven’t tried it out, but it fits perfectly in this discussion.

Re: How we sped up Notion in the browser with WASM SQLite

#68
post #12

Earlier quoted context omitted.

[..] Web SQL Database was a prior API developed by Apple.[12] But Firefox refused to add support for it and argued against it becoming a standard because it would codify the quirks of SQLite.[13][14] It was thus deprecated in favor of IndexedDB.[..] Mozilla again.. The real joke is, Firefox is now the only(?) browser using sqlite out-of-the-box for internal databases.

nope, chromium too. look in your cookies file

Presumably GP meant Mozilla agitated for a Document/KV-store, yet for some inexlicable reason, in their own browser, they chose to implement IndexedDB with SQLite.

They could have used an actual KV store behind it, like chromium did (levelDB IIRC).

Re: How we sped up Notion in the browser with WASM SQLite

#70
post #43

Earlier quoted context omitted.

I'd also point out about AWS cost, which is pretty high, getting IOPS is easy. Getting Redundant IOPS is hard part.

Huh? Not really. AWS is a marvel of engineering in that it can be everyone's redundant IOPS but being your IOPS isn't such a big deal. Most folks are single region and rent-a-datacenter colo operations can get you two racks with separate power/uplink no issue. I hope everyone at least once in their career gets to experience just how god damn fast hardware (especially networking speeds between your own servers) is. Sw…

> I hope everyone at least once in their career gets to experience just how god damn fast hardware (especially networking speeds between your own servers) is.

THIS. I realized cloud disks were much slower than I thought when I ran the same tests in RDS – with a local NVMe cache – against my decade-old Dell R620, with its disks also being NVMe, but via Ceph over Mellanox Infiniband. My server matched or beat the many-generations-newer RDS instance on almost every query.

You can’t get around latency. Even at 1 msec, that’s a maximum of 1000 ops a single thread can do per second, modulo the various buffering and chunking strategies every layer does.

Post reply on HN