ssbc / ssb-db2

A new database for secure-scuttlebutt
47 stars 8 forks source link

use setTimeout in deleteFeed #378

Closed staltz closed 1 year ago

staltz commented 2 years ago

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 with push.values() runs synchronously (it has a while loop internally), and even though the push.asyncMap has the word "async", quite often log.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 for deleteFeed 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:

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?

staltz commented 2 years 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/

staltz commented 2 years ago

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.

arj03 commented 2 years ago

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?

staltz commented 2 years ago

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.

arj03 commented 2 years ago

Ah yes, worker threads is quite exciting!

staltz commented 2 years ago

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.

staltz commented 1 year ago

Bye bye