-
Notifications
You must be signed in to change notification settings - Fork 9
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 optimizations #131
Comments
Benchmarks from 2023-07-13 on branch (obtained with
Summary8MiB:
|
Benchmarks from 2023-07-13 on branch
|
Benchmarks from
|
Benchmarks from
|
Benchmarks from
|
Benchmarks from
Note: removed the |
Quisync performance is not great and should be improved. There are two main areas for this:
Storage performance
Reading blobs
Reading a block involves loading the index nodes from the root to the corresponding leaf node to find the block id and then to load the block itself. This involves multiple db queries. If multliple blocks are read in succession (say when reading a file that consists of multiple blocks), some of the index nodes are shared but we still load them again.
To improve this we should cache the previously loaded nodes/blocks.
Writing blobs
To write a block we need to start a db transaction, load all the index nodes in the path from the root to the block and for each node also all its siblings. Then we need to recalculate the hashes (this is why we need the siblings), then save all the nodes one by one into the db and finally commit the transaction.
This gets very inefficient when multiple blocks are saved in succession because we often load and re-hash the same set of sibling nodes over and over. Also we currently create a new snapshot (and delete the old one) for every written block. Finally performing a lot of small db write transaction is slower than a single large one.
To improve this we should collect the blocks to be written (that is, locator + content) into a memory-only structure and write them all at once at some meaningful point (say after certain number of blocks collected and/or after explicit
flush
). The cache mentioned in the previous section could also help here.Index nodes
When we receive an index node from another peer we always perform an expensive operation called
update_summaries
which involves traversing the index up and down in order to update the block presence checksums. We also use a separate db transaction for every received node.To Improve this we should again collect the received nodes into a memory-only structure and commit them into the db all at once. This can happen when we collect certain number of nodes and/or when the current snapshot becomes complete. The
update_summaries
can then be called only once per this commit. This means that most responses would be processed without involving any db operation at all which should improve throughput. Also the cache might help here as well.Db schema and operations
It's possible that our db schema is not optimal and it might be worth looking into how to improve it. For example, the index nodes tables are not fully normalized (some data is duplicated) and normalizing it might help. Also using integers as primary/foreign keys might be better than using blobs (e.g. block id, locator, ...). We should also check whether our db indices are set up correctly.
Syncing performance
Currently syncing is mostly bottlenecked by the storage so improving the storage also improves syncing and so we should start there. In addition to that, here are some other areas that we might want to look into:
To do
The text was updated successfully, but these errors were encountered: