-
Notifications
You must be signed in to change notification settings - Fork 159
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
Performance cliff with large database #344
Comments
Hmm, interesting. Ya, a few ideas:
|
Here's the output of
Is there anything in this that jumps out at you as suspicious? This is from an index that hasn't hit the performance cliff yet, so if there's a bug, for example in balancing, it might not be manifesting it yet. |
Nope, that all looks quite reasonable. Fragmented space being a little less than 50% is expected, since full pages split into two half full pages. It's interesting that your sync takes so long. My benchmark writes 1M keys in 1.4secs. So 24+ hours for 135M keys seems kinda slow. How do I run this sync myself? |
The 135M keys are just the outputs that remain as of the current chain tip. During sync though, there will be a bunch of insertions and deletions, probably orders of magnitude more than 135M. It's pretty easy to run! You'll need bitcoin core: https://bitcoincore.org/en/download/ Start and sync a bitcoin node by running |
If it's reasonably fast, try uncommenting out the
On our production server, this makes everything much slower. |
When I run ord I get this error:
Do I need to do something to grant it permission to talk to bitcoind, or use something else? |
Ah right, ok that makes sense. When bitcoind is sync'ing does the |
Yup, I think so. My synced node just printed |
Ya, that looks quite reasonable. Is that before or after the big slowdown? |
This is with the "big slowdown" changes backed out, so before the big slowdown. |
I uncommented that line and also turned on info level logs. I ran the sync up to block height 392844, and I think I see the slowdown you're talking about. Each transaction has gone from taking 1-10ms to more like 1000ms. However, it looks expected, the number of ordinals being committed in each transaction has gone up to around a million!
Could the problem be that around that block height people started using Bitcoin more, and so the ordinals are getting mixed around and so each transaction that gets spent includes a large number of ordinal ranges? |
|
That's definitely true, but I don't think it's the source of the slowdown. When this for loop: for input in &tx.input {
outpoint_to_txid.insert(&serialize(&input.previous_output), &txid)?;
} …is enabled it will perform one additional insert per spent output, which doesn't depend on the number of ordinal ranges moving per transaction. So uncommenting it shouldn't cause a slowdown that occurs when the number of ordinal ranges moving per block gets large. Also, without it, the ordinals.com instance syncs reasonably quickly all the way to the chain tip. Here's a graph of the full mainnet sync, without the slowdown: So it definitely slows down as blocks get full, but the average stays around 200ms. Here's a zoomed in view of the end: It's hard to tell, but it looks like the average stays around 200ms/commit. |
Ah yes, ok I see. I added a counter for the number of outpoints, and it's only a few thousand per block |
Ok, so the good news is I don't think it's a bug in redb, but that's also the bad news =P I hacked my benchmark to simulate your workload, it assumes each value is 12 bytes * 100 ordinal range = 1.2kb, and after an initial load of millions of pairs, it writes transactions of 5000 outpoints. I tested against lmdb, with varying sizes for the initial load, and redb performs on par with lmdb (redb seems to scale better actually). However, both of them start to get slow around 8M entries, which is probably around the time that it no longer fits in memory (I have 32GB, but it looks like the OS is only using ~14GB for buff/cache according to
There's a bunch of weird stuff here, like remove is much slower than insert, which doesn't really make sense to me. Will need to look into it further. |
Ok, actually I think the insert performance does make sense. I tested throughput on my disk (Samsung 980 Pro) with We can estimate the insert speed by assuming every write goes directly to disk:
|
Thanks for looking into this! Ahh, damn, I was hoping for an ez fix bug in redb 😭 I tried to simulate the database running out of memory by building an index that was > 1 GiB of memory on a machine with 1 GiB of memory, but didn't run into a cliff. However, that was a small database, so it seems likely that I might just not have seen enough of a performance difference. |
We found this a little while ago, see https://github.com/casey/ord/issues/371, but I was hoping to have more information for you before making an issue here. However, I really haven't been able to figure out the issue, so here I am T_T
The mainnet
ord
database is around 50GiB, and syncs reasonably quickly. It processes one block at a time, without any parallelism, makes one commit per block, and takes around 36 hours to sync when connected to a fully synced bitcoin core node.The main table is
OUTPOINT_TO_ORDINAL_RANGES
, which maps outputs, which are a TXID and a u32 output index, to ordinal ranges, the encoding of which is a little complicated, but are conceptually just(u64, u64)
which give the start and size of each ordinal range in the output.Recently, we added a new table,
OUTPOINT_TO_TXID
, which required a rebuild of the database. However, when the rebuild was underway, we noticed that it was extremely slow, and would take at least 9 days to sync, and the database was around 80 GiB, and wasn't yet at half-way synced. Each block was taking multiple seconds, as opposed to just a few milliseconds. We stopped the sync, disabled writes to the new table, and re-deployed, and the full sync was pretty quick again.One thing that struck me was that the server has 64 GiB of RAM, so maybe the performance cliff happens when the database is larger than available RAM. So, we tried building the database on a machine with 1 GiB of RAM, but didn't notice a similar cliff. So it might be that the degradation only happens when the database is large.
Do you have any suggestions for things we might do to figure out to give you more information, and find out if this is redb issue, or if we're just hitting performance limitations of the box we're on?
The text was updated successfully, but these errors were encountered: