-
Notifications
You must be signed in to change notification settings - Fork 988
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
Consider restoring previous captive core state on startup instead of catchup #2960
Comments
That is a good idea; probably a little more complicated than this though: |
yeah I am aware of the garbage collection issue. I don't think it's very complicated though: we'd just need to carefully evaluate the placement of the garbage collection calls during startup + catchup, and opt-out of it during specific parts of catchup (i.e., bucket apply; GC would still happen during ledger application of course). |
Actually maybe the problem is something entirely different: if what people are trying to do is make "captive core restart fast", then the solution is to have a database setup (sqlite) but not use it to store the ledger (or transactions etc). When setup like this, what core needs to do on startup is to apply buckets to rebuild its in-memory state. With this done, it can even catchup to the network without having to perform a full catchup from history. That way the HAS will be there so this garbage collection problem won't even need to be fixed. |
@ire-and-curses does that sound like it would help with the captive core situation? Basically we would run captive-core in some hybrid mode that will use a small database (sqlite) alongside buckets. This will also allow to keep peer information around, which also helps when restarting a node (today captive core has to re-discover peers with capacity on every restart, and that can take a while). |
Yeah that does sound like it would help. I guess it depends on how the startup time is broken down. Where is the time spent? Where we're coming from is we recently learned from @brahman81 and @jacekn that patching and restarting stand-alone stellar-core has no restart delay. We've been trying to understand what's different in the captive core case. How big would this database be? Does it change anything with the current need to store gigabytes of bucket files? Regarding the original proposal: I think which way to go really depends on this question of what will make the most improvement to initial start up time + implementation cost. |
I just talked to @bartekn about this, so I am adding a few more details:
|
I guess one of the things we probably need before doing this is to quantify all of this:
|
(tried this on my local machine in case it's useful)
Looks like it takes about 80-90 seconds with
Bucket application takes ~30 seconds. |
OK, so it looks like with those numbers the only viable change is what I outlined earlier as the node would only have to rebuild its in memory state (30s), in which case we're still within the window for keeping the node in sync after a restart |
Implementation-wise, one thing to note here is that in order to restore the in-memory state correctly, we need the most recent ledger header (LedgerManager relies on the correct last closed ledger header from what I see). We do not store ledger headers in this mode, but we do store some information in |
I don't think it's more complicated: it's about picking the right "configuration" mode. More complicated is to add new ways to do the same thing (that needs to be tested etc). We already have a mechanism to persist the lcl, it's just (currently) disabled in this mode. To make it work, we may need to enable a very aggressive "maintenance" so that we don't store too many of these but that's about it. |
So I've put together an initial prototype, and was able to join the network in ~30 seconds, which is promising! I do want to clarify a couple of things to make sure we are all on the same page. The API
Would love to hear feedback from the Horizon team on this to make sure I'm understanding this right (@bartekn, @ire-and-curses, @MonsieurNicolas) Implementation commentsOne question I had is around the semantics of "in memory state vs persisted state" during startup. Note: When I say "persisted" state in the context of captive core, I mean "whatever is in the database plus the in-memory LedgerTxn". When I say "in memory" state, I'm talking about the internal state that core keeps track of to correctly proceed (such as last closed ledger, assumed bucket state, last Herder state etc). I know that in this case "persisted" is not actually fully persisted, but it's easier to mentally separate the two categories this way (at least for me!) So the typical startup flow is: start the app, load state from the database, reason about what to do based on that state. With the introduction of this hybrid mode, our "persisted state" is inconsistent on startup, so core cannot setup the in-memory state correctly (i.e., ledger headers say "we're at ledger X", whereas LedgerTxn has no state at all). So I'm restoring the correct state first before officially "starting the app and loading last known state". This seems like a safer thing to do and the "restore state" code does not depend on any internal state (i.e., it only depends on persisted buckets, HAS, etc), but I wanted to double check that there isn't anything missing in this approach @MonsieurNicolas @graydon. |
Overall this makes sense to me. The one thing I am not sure about is having to call On your last point, yeah that seems to be the best way forward as to keep things separate. The good news there is we have "state", so it should be relatively easy to spin up/spin down (if needed) a different "app" before doing the rest of the work. |
I think it would help me understand the strategy if you could break down which tables (and which rows in the |
As suggested by @bartekn, consider skipping the download of a particular bucket if it's already present in the buckets folder. This would be useful, as captive core has to re-download all the buckets upon re-start. Note that we should still verify buckets, to ensure that we are not processing invalid buckets.
The text was updated successfully, but these errors were encountered: