better-sqlite3 icon indicating copy to clipboard operation
better-sqlite3 copied to clipboard

Lowering level for multi-threading

Open loromagnoni opened this issue 1 year ago • 5 comments

Hi! My Electron application opens a SQLite connection through BetterSQLite3 from a Electron Renderer process with Node integration enabled.

To test concurrency I did the following experiments:

  • Send a query request from Electron Renderer to Electron Main, propagated then to a Node worker thread which executes the query.
  • Send a query requests from Electron Renderer to a web worker which executes the query.

In both scenarios the communication overhead was extremely noticeable. All my queries are handled by SQLite in less than 25ms, with these two approaches the total roundtrip duration goes from 2x to 10x.

I am wondering if handling multi-threading at the driver level could avoid the communication overhead experienced when handling it at the application level. Do you have any idea on this? Is it even possible in Electron to manage thread at a native level?

Thank you for your time

loromagnoni avatar Dec 16 '24 11:12 loromagnoni

The problem with multi-threading at the driver level is that the thread would be running C code, not user-land JavaScript (unless the thread hosted its own instance of of V8, which would have significant overhead and gotchyas), thus, many of the features supported by better-sqlite3 would not work, including:

  • custom functions
  • custom aggregates
  • custom virtual tables
  • loading extensions
  • re-using prepared statements
  • etc.

I'm surprised that the overhead you're experiencing is so high. It could be worth investigating that further.

JoshuaWise avatar Dec 16 '24 16:12 JoshuaWise

with these two approaches the total roundtrip duration goes from 2x to 10x.

How are you measuring this? Serialization of ipc messages can synchronously blocks both main / render (losing all concurrency). So this might be an issue with how you're setting things up.

  • Send a query request from Electron Renderer to Electron Main, propagated then to a Node worker thread which executes the query.

How is this implemented? Via ipc or HTTP?

It would be great if you could provide a minimal Electron app that demonstrates the different approaches and performance issues.

Prinzhorn avatar Dec 17 '24 06:12 Prinzhorn

How are you measuring this?

Measuring my endpoints start and end timestamps. The only step these endpoints perform are SQL queries.

How is this implemented? Via ipc or HTTP?

The communication between Renderer and Main is made through Electron IPC indeed.

I will share a minimal app to showcase the different behaviours.

loromagnoni avatar Dec 17 '24 09:12 loromagnoni

If you use Electron's MessageChannels, you can achieve significantly better results than via normal IPC. (In my tests it was slightly faster than HTTP.)

nikwen avatar Jan 06 '25 16:01 nikwen

Also keep in mind that sometimes it's JSON serialization and deserialization which is slow, not the actual IPC data transfer. In that case, reduce the amount of JSON (de)serialization necessary.

nikwen avatar Jan 06 '25 16:01 nikwen