Closed staltz closed 1 year ago
Well here's something new I learned:
I used to think the main process is the ideal place for “heavy lifting” because it wouldn’t block the UI. That’s wrong actually — if you do CPU intensive work in the main process, it’ll lock up all your renderer processes (and give you the infamous beachball on macOS).
https://cameronnokes.com/blog/deep-dive-into-electron's-main-and-renderer-processes/
Well, it might be that this is just me using Electron wrong (it's very easy to use Electron wrong!) https://www.electronjs.org/docs/v14-x-y/tutorial/performance#3-blocking-the-main-process
I'll try to move the whole SSB backend to a worker_thread and let's see if this issue is still relevant after that.
Hmm, would it be possible to use TooHot here and be able to configure it that way it would be possible to disabled this if one just want the performance?
Yes, I also thought of changing the API from deleteFeed(id, cb)
to deleteFeed(id, opts, cb)
.
About TooHot, I vaguely recall what did it do for this case, if I remember correctly there was still considerable freezing going on. Maybe the reason is that the synchronous code is not that CPU intensive, it's just synchronous/blocking.
But first, I'm curious to use worker_threads for the backend instead of the main renderer, so it's safe to park this PR for now.
Ah yes, worker threads is quite exciting!
I would use worker_threads in a very simple way that gives no performance boost (other than freeing the UI thread): just one big thread for the whole SSB secret-stack. Exploring a pool of worker_threads for performance is quite another beast to tackle.
Bye bye
This PR is just a conversation starter.
In Manyverse I'm running a lot of
deleteFeed
(for all the feeds at negative hops distance), and some of the feeds are large (one of them has 17MB worth of messages on the log).I noticed that if I try to use the app while
deleteFeed
is running for a large feed, the UI freezes entirely, and then goes back to normal after ~6sec. Ignore the fact that the Electron main (where ssb-db2 runs) should be a different thread to the Electron renderer (where the HTML is), so one thread should not affect the other, but :man_shrugging: .Anyway, what seems to be happening is that
push-stream
withpush.values()
runs synchronously (it has awhile
loop internally), and even though thepush.asyncMap
has the word "async", quite oftenlog.del
runs synchronously too, because of block caches in AAOL. Only when there is a cache miss in AAOL will this pipeline have a "break" for actual async I/O with the filesystem.I made this experiment with
setTimeout
and it clearly helped the UI to not freeze. Obviously this made the total time longer fordeleteFeed
to complete. Before: ~6s for one heavy feed, after: ~50s for one heavy feed. But for my purposes it's more important that deletes don't freeze the UI than it is to delete ASAP. I know other people will have different priorities and it's important that deleteFeed can run as fast as it can.In fact, there are two important parts here:
query(where(author(feedId)), asOffsets(), toCallback
)push-stream
pipeline forlog.del
The 2nd is much heavier than the first, but sometimes, if there is a huge amount of messages in the 1st part, the app UI also freezes. Ideally it would be good to solve that one too, which is a jitdb responsibility, but for my purposes, the 1st part freezing is not as bad as the 2nd part freezing.
Thoughts?