-
Notifications
You must be signed in to change notification settings - Fork 340
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
Fixing the svm account serialization for performance #4848
Fixing the svm account serialization for performance #4848
Conversation
The Firedancer team maintains a line-for-line reimplementation of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear to me why this change is correct. When we calculate the size, what exactly are we missing?
I'm not saying that the code is perfect, it would just be good to know what the bug is rather than adding some random constants
@@ -40,7 +40,7 @@ struct Serializer { | |||
impl Serializer { | |||
fn new(size: usize, start_addr: u64, aligned: bool, copy_account_data: bool) -> Serializer { | |||
Serializer { | |||
buffer: AlignedMemory::with_capacity(size), | |||
buffer: AlignedMemory::with_capacity_zeroed(size), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would zeroing improve perf? In anything it should be slower
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is faster because fill_write during account serialization is already initialized so only set_len for vector is called, where as if we only increase the capacity vector resize is called which inturn call vector extend with value 0 which seems to be more expensive.
There are few bytes missing, 4 bytes added after executable, datalen allocated 4 bytes instead of 8 bytes, each account has one align offset bytes not included. |
+ 4 // padding of 4 bytes after executable | ||
+ size_of::<u64>() // original_data_len |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this padding necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because of this :
s.write_all(&[0u8, 0, 0, 0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That matched up with + size_of::<u32>() // original_data_len
Please try to reproduce this issue with a test case that shows the size calculation is incorrect. I'm running a mainet validator with the following patch:
Nothing is coming up - I don't think there is a problem here |
Problem
Performance issue with svm during serialization of accounts forces resize of memory because the initial size is not correctly calculated. This impact the performance of the svm a lot with current benchmarks and profiling with openbook contract we see the average performance jump up from 6360 tps to 8144 tps. This is around 30 % improvement which can be verified by profiling which spends 30 percent of the time in resizing.
Summary of Changes
Correctly calculating the initial size of the memory and adding few extra bytes to capacity to avoid potential memory reallocations.
Another change is making use of the method
AlignedMemory::with_capacity_zeroed(size)
which avoid any calls to resize which makes performance much faster.To benchmark the svm code we use following repository.
https://github.com/godmodegalactus/simulate-svm-contract
This repository creates continuously place order on openbook market and also runs crank instruction from time to time. The figures are generated after running the benchmark program for 500s to get the average tps.
Unoptimized serializer :
Optimized serialized with preallocated and zeroed memory
Optimized serialize without zeroed memory
Fixes #
No feature gates