Skip to content
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

[Execution] Do not depend on string conversion in register set tracking #3529

Merged
merged 2 commits into from
Nov 9, 2022

Conversation

SaveTheRbtz
Copy link
Contributor

@SaveTheRbtz SaveTheRbtz commented Nov 8, 2022

This PR:

  • converts map[string]flow.RegisterID to map[flow.RegisterID]struct{} to represent sets.
  • switches Delta from map[string]flow.RegisterEntry to map[flow.RegisterID]flow.RegisterValue to save a bit of space.

Currently these are responsible for ~15% of memory allocations:
Screen Shot 2022-11-07 at 9 50 17 PM

name                             old time/op    new time/op    delta
ComputeBlock/16/cols/128/txes-8     1.83s ± 3%     1.69s ± 2%   -7.59%  (p=0.000 n=10+10)

name                             old alloc/op   new alloc/op   delta
ComputeBlock/16/cols/128/txes-8    1.34GB ± 1%    1.21GB ± 2%   -9.38%  (p=0.000 n=9+10)

name                             old allocs/op  new allocs/op  delta
ComputeBlock/16/cols/128/txes-8     19.8M ± 0%     17.1M ± 0%  -13.48%  (p=0.000 n=8+8)

@codecov-commenter
Copy link

codecov-commenter commented Nov 8, 2022

Codecov Report

Merging #3529 (a1b0c64) into master (fcdef25) will increase coverage by 4.68%.
The diff coverage is 88.23%.

@@            Coverage Diff             @@
##           master    #3529      +/-   ##
==========================================
+ Coverage   55.22%   59.90%   +4.68%     
==========================================
  Files         755      149     -606     
  Lines       69164    16961   -52203     
==========================================
- Hits        38196    10161   -28035     
+ Misses      27834     5972   -21862     
+ Partials     3134      828    -2306     
Flag Coverage Δ
unittests 59.90% <88.23%> (+4.68%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
engine/execution/state/delta/delta.go 61.40% <69.23%> (-4.23%) ⬇️
engine/execution/state/delta/view.go 76.82% <100.00%> (ø)
engine/collection/synchronization/engine.go 68.97% <0.00%> (ø)
model/flow/ledger.go
module/chunks/chunkVerifier.go
utils/unittest/fixtures.go
fvm/environment/contract_reader.go
cmd/execution_config.go
utils/binstat/binstat.go
storage/badger/operation/seals.go
... and 600 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 8, 2022

FVM Benchstat comparison

This branch with compared with the base branch onflow:master commit 6f64410

The command (for i in {1..10}; do go test ./fvm ./engine/execution/computation --bench . --tags relic -shuffle=on --benchmem --run ^$; done) was used.

Collapsed results for better readability

old.txtnew.txt
time/opdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/reference_tx-241.8ms ±15%38.8ms ± 5%~(p=0.079 n=10+9)
RuntimeTransaction/convert_int_to_string-241.8ms ± 9%40.8ms ± 5%~(p=0.243 n=9+10)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-242.7ms ±10%45.5ms ±14%~(p=0.243 n=9+10)
RuntimeTransaction/get_signer_address-240.3ms ± 5%42.0ms ±18%~(p=0.912 n=10+10)
RuntimeTransaction/get_public_account-243.8ms ±11%42.2ms ± 5%~(p=0.315 n=10+10)
RuntimeTransaction/get_account_and_get_storage_capacity-2340ms ± 5%329ms ± 9%~(p=0.105 n=10+10)
RuntimeTransaction/get_signer_receiver-263.8ms ± 9%62.4ms ± 7%~(p=0.529 n=10+10)
RuntimeTransaction/transfer_tokens-2277ms ± 8%279ms ± 5%~(p=0.842 n=10+9)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-248.1ms ± 6%47.0ms ± 4%~(p=0.053 n=10+9)
RuntimeTransaction/create_new_account-21.06s ± 5%1.05s ± 4%~(p=0.579 n=10+10)
RuntimeTransaction/call_empty_contract_function-242.9ms ± 8%42.4ms ± 4%~(p=0.436 n=10+10)
RuntimeTransaction/emit_event-258.7ms ±10%59.4ms ± 6%~(p=0.481 n=10+10)
RuntimeTransaction/borrow_array_from_storage-2164ms ± 6%163ms ± 3%~(p=0.829 n=10+8)
RuntimeTransaction/copy_array_from_storage-2167ms ± 7%168ms ± 4%~(p=0.912 n=10+10)
RuntimeTransaction/get_signer_vault-249.1ms ± 5%47.8ms ± 3%−2.64%(p=0.019 n=9+9)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-26.34s ± 5%6.13s ± 5%−3.41%(p=0.009 n=10+10)
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/get_account_and_get_storage_used-247.1ms ± 5%45.5ms ± 5%−3.48%(p=0.043 n=10+9)
RuntimeNFTBatchTransfer-2146ms ± 5%141ms ± 4%−3.75%(p=0.006 n=10+8)
RuntimeTransaction/load_and_save_long_string_on_signers_address-2100ms ± 7%96ms ± 2%−3.90%(p=0.015 n=10+10)
RuntimeTransaction/get_account_and_get_available_balance-2388ms ± 4%369ms ± 2%−4.87%(p=0.000 n=8+9)
RuntimeTransaction/get_account_and_get_balance-2432ms ± 3%410ms ± 3%−5.15%(p=0.000 n=8+10)
 
computationdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/reference_tx-2202 ± 0%202 ± 0%~(all equal)
RuntimeTransaction/convert_int_to_string-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-2502 ± 0%502 ± 0%~(all equal)
RuntimeTransaction/get_signer_address-2302 ± 0%302 ± 0%~(all equal)
RuntimeTransaction/get_public_account-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_balance-21.00k ± 0%1.00k ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_available_balance-22.60k ± 0%2.60k ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_storage_used-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_storage_capacity-21.30k ± 0%1.30k ± 0%~(all equal)
RuntimeTransaction/get_signer_vault-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/get_signer_receiver-2602 ± 0%602 ± 0%~(all equal)
RuntimeTransaction/transfer_tokens-23.50k ± 0%3.50k ± 0%~(all equal)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-2602 ± 0%602 ± 0%~(all equal)
RuntimeTransaction/load_and_save_long_string_on_signers_address-2602 ± 0%602 ± 0%~(all equal)
RuntimeTransaction/create_new_account-2202 ± 0%202 ± 0%~(all equal)
RuntimeTransaction/call_empty_contract_function-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/emit_event-2602 ± 0%602 ± 0%~(all equal)
RuntimeTransaction/borrow_array_from_storage-22.60k ± 0%2.60k ± 0%~(all equal)
RuntimeTransaction/copy_array_from_storage-22.60k ± 0%2.60k ± 0%~(all equal)
 
interactionsdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/reference_tx-244.3k ± 0%44.3k ± 0%~(all equal)
RuntimeTransaction/convert_int_to_string-244.3k ± 0%44.3k ± 0%~(all equal)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-244.3k ± 0%44.3k ± 0%~(all equal)
RuntimeTransaction/get_signer_address-244.3k ± 0%44.3k ± 0%~(all equal)
RuntimeTransaction/get_public_account-244.3k ± 0%44.3k ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_balance-216.7M ± 0%16.7M ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_available_balance-25.13M ± 0%5.13M ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_storage_used-244.3k ± 0%44.3k ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_storage_capacity-25.13M ± 0%5.13M ± 0%~(all equal)
RuntimeTransaction/get_signer_vault-244.5k ± 0%44.5k ± 0%~(all equal)
RuntimeTransaction/get_signer_receiver-244.9k ± 0%44.9k ± 0%~(all equal)
RuntimeTransaction/transfer_tokens-245.2k ± 0%45.2k ± 0%~(all equal)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-244.4k ± 0%44.4k ± 0%~(all equal)
RuntimeTransaction/load_and_save_long_string_on_signers_address-247.2k ± 0%47.2k ± 0%~(all equal)
RuntimeTransaction/create_new_account-28.39M ± 0%8.39M ± 0%~(p=0.248 n=10+9)
RuntimeTransaction/call_empty_contract_function-244.5k ± 0%44.5k ± 0%~(all equal)
RuntimeTransaction/emit_event-244.5k ± 0%44.5k ± 0%~(all equal)
RuntimeTransaction/borrow_array_from_storage-249.7k ± 0%49.7k ± 0%~(all equal)
RuntimeTransaction/copy_array_from_storage-249.7k ± 0%49.7k ± 0%~(all equal)
 
alloc/opdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/convert_int_to_string-235.1MB ± 4%34.8MB ± 4%~(p=0.579 n=10+10)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-235.6MB ± 7%35.4MB ± 5%~(p=0.796 n=10+10)
RuntimeTransaction/get_signer_address-234.9MB ± 2%34.7MB ± 3%~(p=0.393 n=10+10)
RuntimeTransaction/get_public_account-236.5MB ± 3%35.8MB ± 3%~(p=0.052 n=10+10)
RuntimeTransaction/get_account_and_get_storage_used-236.8MB ± 6%36.4MB ± 4%~(p=0.579 n=10+10)
RuntimeTransaction/get_signer_receiver-241.0MB ± 6%40.8MB ± 9%~(p=0.912 n=10+10)
RuntimeTransaction/transfer_tokens-282.7MB ± 4%81.5MB ± 4%~(p=0.089 n=10+10)
RuntimeTransaction/call_empty_contract_function-235.5MB ± 3%35.0MB ± 1%~(p=0.230 n=10+7)
RuntimeTransaction/emit_event-240.2MB ± 5%40.7MB ± 7%~(p=0.529 n=10+10)
RuntimeTransaction/borrow_array_from_storage-269.2MB ± 3%68.0MB ± 4%~(p=0.065 n=9+10)
RuntimeTransaction/copy_array_from_storage-281.5MB ± 4%81.3MB ± 4%~(p=0.796 n=10+10)
RuntimeTransaction/get_signer_vault-237.6MB ± 2%36.8MB ± 4%−2.30%(p=0.028 n=9+10)
RuntimeTransaction/reference_tx-235.4MB ± 2%34.4MB ± 3%−2.93%(p=0.004 n=9+10)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-236.4MB ± 5%35.2MB ± 3%−3.36%(p=0.004 n=10+10)
RuntimeTransaction/get_account_and_get_available_balance-2109MB ± 3%105MB ± 4%−4.02%(p=0.000 n=10+10)
RuntimeNFTBatchTransfer-255.6MB ± 4%53.3MB ± 8%−4.05%(p=0.043 n=10+10)
RuntimeTransaction/load_and_save_long_string_on_signers_address-255.8MB ± 4%53.5MB ± 5%−4.16%(p=0.003 n=10+10)
RuntimeTransaction/get_account_and_get_storage_capacity-2105MB ± 3%100MB ± 4%−4.97%(p=0.000 n=10+10)
RuntimeTransaction/get_account_and_get_balance-2128MB ± 0%120MB ± 3%−6.40%(p=0.000 n=9+10)
RuntimeTransaction/create_new_account-2196MB ± 3%183MB ± 1%−6.43%(p=0.000 n=10+10)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-21.28GB ± 1%1.16GB ± 1%−9.66%(p=0.000 n=10+10)
 
allocs/opdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/transfer_tokens-2860k ± 0%844k ± 0%−1.80%(p=0.000 n=10+10)
RuntimeTransaction/borrow_array_from_storage-2346k ± 0%337k ± 0%−2.84%(p=0.000 n=10+10)
RuntimeTransaction/copy_array_from_storage-2303k ± 0%293k ± 0%−3.24%(p=0.000 n=10+10)
RuntimeTransaction/get_signer_receiver-2204k ± 0%195k ± 0%−4.52%(p=0.000 n=10+10)
RuntimeTransaction/emit_event-2142k ± 0%133k ± 0%−6.46%(p=0.000 n=10+10)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-2133k ± 0%124k ± 0%−6.71%(p=0.000 n=10+10)
RuntimeTransaction/get_signer_vault-2132k ± 0%123k ± 0%−6.82%(p=0.000 n=10+10)
RuntimeTransaction/get_public_account-2115k ± 0%106k ± 0%−7.61%(p=0.000 n=10+10)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-2113k ± 0%104k ± 0%−7.74%(p=0.000 n=10+10)
RuntimeTransaction/convert_int_to_string-2102k ± 0%93k ± 0%−8.60%(p=0.000 n=8+10)
RuntimeTransaction/call_empty_contract_function-2104k ± 0%95k ± 0%−8.79%(p=0.000 n=10+10)
RuntimeTransaction/get_signer_address-293.8k ± 0%85.1k ± 0%−9.33%(p=0.000 n=10+8)
RuntimeTransaction/reference_tx-289.6k ± 0%80.9k ± 0%−9.77%(p=0.000 n=10+10)
RuntimeNFTBatchTransfer-2296k ± 0%265k ± 0%−10.63%(p=0.000 n=10+10)
RuntimeTransaction/create_new_account-22.55M ± 0%2.28M ± 0%−10.72%(p=0.000 n=10+9)
RuntimeTransaction/get_account_and_get_available_balance-21.35M ± 0%1.20M ± 0%−11.16%(p=0.000 n=10+10)
RuntimeTransaction/get_account_and_get_storage_capacity-21.22M ± 0%1.08M ± 0%−11.54%(p=0.000 n=10+9)
RuntimeTransaction/get_account_and_get_balance-21.51M ± 0%1.32M ± 0%−12.65%(p=0.000 n=8+10)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-219.8M ± 0%17.2M ± 0%−12.98%(p=0.000 n=10+10)
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/get_account_and_get_storage_used-2135k ± 0%116k ± 0%−13.85%(p=0.000 n=10+10)
RuntimeTransaction/load_and_save_long_string_on_signers_address-2234k ± 0%199k ± 0%−15.05%(p=0.000 n=10+10)
 
us/txdelta
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-23.10k ± 5%2.99k ± 5%−3.41%(p=0.009 n=10+10)
 

@SaveTheRbtz SaveTheRbtz changed the title XXX [Execution] Do not depend on string conversion in register set tracking Nov 8, 2022
@SaveTheRbtz SaveTheRbtz force-pushed the rbtz/optimizeLedger branch 2 times, most recently from c29ccb7 to 3b6de45 Compare November 8, 2022 06:25
Comment on lines 20 to +21
func (r *RegisterID) String() string {
ownerLen := len(r.Owner)

requiredLen := ((ownerLen + len(r.Key)) * 2) + 1

arr := make([]byte, requiredLen)

hex.Encode(arr, []byte(r.Owner))

arr[2*ownerLen] = byte('/')

hex.Encode(arr[(2*ownerLen)+1:], []byte(r.Key))

return string(arr)
return fmt.Sprintf("%x/%x", r.Owner, r.Key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why we were doing it this way in the first place, I think it suppose to be some sort of optimized way of doing it

Copy link
Contributor Author

@SaveTheRbtz SaveTheRbtz Nov 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. It is about 2x fast as the Sprintf. The main problem here is that it was not needed at all -- we were using this for map indexing, instead of just using the struct itself (which is infinitely faster and does not require allocations.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it, then all good.

@SaveTheRbtz SaveTheRbtz marked this pull request as ready for review November 8, 2022 18:32

for _, v := range d.Data {
data = append(data, v)
for k, v := range d.Data {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a waste. sorting then splitting into two list. maybe just return the original sorted list, or change the sorter

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to suggest a similar thing, I think we don't need to sort based on both key and values since the key is used for the Data map is going to be anyway unique, sorting based on the key but appending the values while we are doing it through the sort method might be the more optimized approach here. I see with the current code you were trying to maintain the same logic but I think in this case is fine to change the sort to be based on the key, considering the less implementation of the KeyEntry is only limited to keys.

Copy link
Member

@ramtinms ramtinms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice find, looks good to me, I think the original definition of Data struct was because of a legacy structure of Delta and it makes a lot of sense to optimize it this way.

Just put a minor suggestion

@SaveTheRbtz
Copy link
Contributor Author

Ok. I'll land this as is to minimize the updates and followup with the PR to simplify RegisterUpdates.