flow-go icon indicating copy to clipboard operation
flow-go copied to clipboard

FVM meter settings pre-fetch

Open Tonix517 opened this issue 2 years ago • 9 comments

In FVM RunV2(), meter setting values are read from state for each transaction, which is unnecessary. Now we move this out of tx execution up to per-collection level - meter setting values are not read once per transaction before tx.

NOTE: this is a breaking change.

  • Ideally all EN and VN nodes should be deployed at the same time to avoid EN disagreement or VN verification failure.
  • Flow emulator should also be updated afterwards to reflect this behavior change since it calls FVM.RunV2() too.

Test

  • [X] existing and newly added UT
  • [X] running benchmark test on localnet and monitor everything

Performance

  • Benchstat report in this PR
  • pprof from localnet with the same set of benchmark testing before optimization: getEnvironmentParams-master

after optimization: getEnvironmentParams-opt

Tonix517 avatar Sep 15 '22 21:09 Tonix517

you will also need to prefetch and cache the state (GetEnvironmentMeterParameters doesn't do that currently). take a look at handler/program.go to see how it steals the state from the stateTransaction. you will need to do something similar here

pattyshack avatar Sep 19 '22 16:09 pattyshack

you will also need to prefetch and cache the state (GetEnvironmentMeterParameters doesn't do that currently). take a look at handler/program.go to see how it steals the state from the stateTransaction. you will need to do something similar here

That should not be necessary since this is done per collection and a collection is also what gets sent to the versifiers. So as long as the touches happen once per collection, the VNs should get all the info needed. Unless i missed something...

janezpodhostnik avatar Sep 19 '22 18:09 janezpodhostnik

Thanks for the suggestion. Now I have another question: how often, and when, are meter settings mutated? In this draft PR we are trying to read the state at the beginning of every collection. If this state can be mutated in the middle of one collection (like some tx can mutate), then we will not be able to do per collection state reading; but if this state is mutated even less frequent than collection level, we can do even less state polling. @janezpodhostnik

you will also need to prefetch and cache the state (GetEnvironmentMeterParameters doesn't do that currently). take a look at handler/program.go to see how it steals the state from the stateTransaction. you will need to do something similar here

Tonix517 avatar Sep 19 '22 18:09 Tonix517

To add up: to make sure meter setting state regs are sent over to VN for verification purposes, we will still need to touch those reg per collection.

Thanks for the suggestion. Now I have another question: how often, and when, are meter settings mutated? In this draft PR we are trying to read the state at the beginning of every collection. If this state can be mutated in the middle of one collection (like some tx can mutate), then we will not be able to do per collection state reading; but if this state is mutated even less frequent than collection level, we can do even less state polling. @janezpodhostnik

you will also need to prefetch and cache the state (GetEnvironmentMeterParameters doesn't do that currently). take a look at handler/program.go to see how it steals the state from the stateTransaction. you will need to do something similar here

Tonix517 avatar Sep 19 '22 18:09 Tonix517

you will also need to prefetch and cache the state (GetEnvironmentMeterParameters doesn't do that currently). take a look at handler/program.go to see how it steals the state from the stateTransaction. you will need to do something similar here

That should not be necessary since this is done per collection and a collection is also what gets sent to the versifiers. So as long as the touches happen once per collection, the VNs should get all the info needed. Unless i missed something...

you still need to capture the state once per collection, right now, GetEnvironmentMeterParameters discards that state?

pattyshack avatar Sep 19 '22 18:09 pattyshack

Thanks for the suggestion. Now I have another question: how often, and when, are meter settings mutated? In this draft PR we are trying to read the state at the beginning of every collection. If this state can be mutated in the middle of one collection (like some tx can mutate), then we will not be able to do per collection state reading; but if this state is mutated even less frequent than collection level, we can do even less state polling. @janezpodhostnik

I've added the same question. sounds like it's safe to assume that the meter parameters are never modified within a block (it's updated at the end of a block). @janezpodhostnik can confirm

pattyshack avatar Sep 19 '22 18:09 pattyshack

parameters are never modified within a block

That's both true and not :smile:. The transaction to modify the parameters can happen in the middle of a block (and in the middle of a collection), but if we move the read of the parameters to read once per collection, then the new parameters will be effective only in the next collections. This is fine, but is good to keep in mind.

janezpodhostnik avatar Sep 20 '22 15:09 janezpodhostnik

FVM Benchstat comparison

This branch with compared with the base branch onflow:master commit a7a69d24bb28a4c909376d3b94f0d5e56dbffe25

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
RuntimeNFTBatchTransfer-2133ms ± 9%130ms ± 3%~(p=0.167 n=9+8)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-235.9ms ± 9%35.8ms ±12%~(p=0.853 n=10+10)
RuntimeTransaction/get_public_account-237.0ms ±14%35.1ms ±22%~(p=0.211 n=9+10)
RuntimeTransaction/get_account_and_get_balance-2340ms ± 1%352ms ± 8%~(p=0.400 n=9+10)
RuntimeTransaction/get_account_and_get_available_balance-2323ms ± 6%318ms ± 6%~(p=0.190 n=10+10)
RuntimeTransaction/get_account_and_get_storage_used-239.6ms ±12%38.6ms ±11%~(p=0.393 n=10+10)
RuntimeTransaction/get_account_and_get_storage_capacity-2273ms ± 2%270ms ± 3%~(p=0.278 n=10+9)
RuntimeTransaction/get_signer_vault-242.4ms ± 5%40.8ms ± 9%~(p=0.247 n=10+10)
RuntimeTransaction/get_signer_receiver-253.0ms ± 3%52.8ms ± 9%~(p=0.631 n=10+10)
RuntimeTransaction/transfer_tokens-2244ms ± 3%241ms ± 3%~(p=0.113 n=10+9)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-242.3ms ±10%42.2ms ± 9%~(p=0.796 n=10+10)
RuntimeTransaction/load_and_save_long_string_on_signers_address-290.0ms ± 4%89.1ms ± 7%~(p=0.315 n=10+10)
RuntimeTransaction/create_new_account-21.00s ± 3%0.98s ± 1%~(p=0.093 n=9+8)
RuntimeTransaction/call_empty_contract_function-236.0ms ±12%34.5ms ±10%~(p=0.247 n=10+10)
RuntimeTransaction/emit_event-252.7ms ±10%51.6ms ± 6%~(p=0.393 n=10+10)
RuntimeTransaction/copy_array_from_storage-2162ms ± 5%158ms ± 4%~(p=0.053 n=10+9)
RuntimeTransaction/borrow_array_from_storage-2156ms ± 2%153ms ± 2%−2.09%(p=0.003 n=9+9)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-25.82s ± 4%5.59s ± 4%−3.95%(p=0.003 n=10+9)
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/convert_int_to_string-235.6ms ±14%32.6ms ±15%−8.47%(p=0.015 n=10+10)
RuntimeTransaction/get_signer_address-233.2ms ±10%30.3ms ±12%−8.64%(p=0.009 n=10+10)
RuntimeTransaction/reference_tx-232.0ms ±12%28.8ms ± 9%−9.99%(p=0.003 n=10+9)
 
alloc/opdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeNFTBatchTransfer-257.6MB ± 3%57.6MB ± 4%~(p=0.739 n=10+10)
RuntimeTransaction/convert_int_to_string-238.2MB ± 6%36.5MB ±10%~(p=0.280 n=10+10)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-238.0MB ± 9%38.4MB ± 8%~(p=0.579 n=10+10)
RuntimeTransaction/get_public_account-238.9MB ± 6%38.1MB ± 9%~(p=0.436 n=10+10)
RuntimeTransaction/get_account_and_get_balance-2130MB ± 1%129MB ± 4%~(p=0.133 n=9+10)
RuntimeTransaction/get_account_and_get_available_balance-2113MB ± 2%113MB ± 3%~(p=0.739 n=10+10)
RuntimeTransaction/get_account_and_get_storage_used-239.2MB ±10%38.9MB ± 8%~(p=0.631 n=10+10)
RuntimeTransaction/get_account_and_get_storage_capacity-2106MB ± 4%106MB ± 4%~(p=0.631 n=10+10)
RuntimeTransaction/get_signer_vault-240.1MB ± 6%39.3MB ± 7%~(p=0.393 n=10+10)
RuntimeTransaction/get_signer_receiver-242.0MB ± 3%42.5MB ± 8%~(p=0.133 n=9+10)
RuntimeTransaction/transfer_tokens-288.8MB ± 3%88.5MB ± 3%~(p=0.739 n=10+10)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-240.0MB ± 9%40.1MB ± 5%~(p=0.684 n=10+10)
RuntimeTransaction/load_and_save_long_string_on_signers_address-256.7MB ± 3%56.0MB ± 3%~(p=0.113 n=9+10)
RuntimeTransaction/create_new_account-2201MB ± 1%201MB ± 3%~(p=0.063 n=10+10)
RuntimeTransaction/call_empty_contract_function-237.7MB ±11%37.5MB ± 7%~(p=0.853 n=10+10)
RuntimeTransaction/emit_event-242.2MB ± 9%41.7MB ± 4%~(p=0.579 n=10+10)
RuntimeTransaction/borrow_array_from_storage-269.2MB ± 4%69.1MB ± 3%~(p=0.579 n=10+10)
RuntimeTransaction/copy_array_from_storage-282.2MB ± 2%82.2MB ± 2%~(p=0.720 n=10+9)
RuntimeTransaction/reference_tx-237.5MB ± 7%35.6MB ± 7%−5.01%(p=0.023 n=10+10)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-21.34GB ± 1%1.27GB ± 1%−5.05%(p=0.000 n=10+10)
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/get_signer_address-237.6MB ± 7%35.6MB ± 7%−5.23%(p=0.010 n=9+10)
 
allocs/opdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/create_new_account-22.67M ± 0%2.67M ± 0%−0.23%(p=0.000 n=10+10)
RuntimeTransaction/get_account_and_get_balance-21.51M ± 0%1.51M ± 0%−0.41%(p=0.000 n=10+10)
RuntimeTransaction/get_account_and_get_available_balance-21.40M ± 0%1.39M ± 0%−0.43%(p=0.000 n=10+9)
RuntimeTransaction/get_account_and_get_storage_capacity-21.24M ± 0%1.23M ± 0%−0.49%(p=0.000 n=10+10)
RuntimeTransaction/transfer_tokens-2934k ± 0%928k ± 0%−0.64%(p=0.000 n=9+10)
RuntimeTransaction/borrow_array_from_storage-2368k ± 0%362k ± 0%−1.65%(p=0.000 n=10+10)
RuntimeTransaction/copy_array_from_storage-2324k ± 0%318k ± 0%−1.87%(p=0.000 n=8+8)
RuntimeNFTBatchTransfer-2290k ± 0%285k ± 0%−2.01%(p=0.000 n=8+9)
RuntimeTransaction/load_and_save_long_string_on_signers_address-2231k ± 0%225k ± 0%−2.62%(p=0.000 n=10+10)
RuntimeTransaction/get_signer_receiver-2203k ± 0%197k ± 0%−2.98%(p=0.000 n=10+10)
RuntimeTransaction/emit_event-2136k ± 0%130k ± 0%−4.45%(p=0.000 n=10+10)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-2129k ± 0%123k ± 0%−4.70%(p=0.000 n=10+10)
RuntimeTransaction/get_account_and_get_storage_used-2128k ± 0%122k ± 0%−4.73%(p=0.000 n=10+10)
RuntimeTransaction/get_signer_vault-2127k ± 0%121k ± 0%−4.79%(p=0.000 n=10+10)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-2107k ± 0%101k ± 0%−5.65%(p=0.000 n=10+10)
RuntimeTransaction/get_public_account-2107k ± 0%101k ± 0%−5.66%(p=0.000 n=10+10)
RuntimeTransaction/call_empty_contract_function-295.6k ± 0%89.5k ± 0%−6.34%(p=0.000 n=10+10)
RuntimeTransaction/convert_int_to_string-292.9k ± 0%86.8k ± 0%−6.53%(p=0.000 n=10+10)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-220.5M ± 0%19.2M ± 0%−6.61%(p=0.000 n=10+10)
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/get_signer_address-283.9k ± 0%77.8k ± 0%−7.24%(p=0.000 n=10+10)
RuntimeTransaction/reference_tx-278.7k ± 0%72.6k ± 0%−7.72%(p=0.000 n=10+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%~(all equal)
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)
 
us/txdelta
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-22.84k ± 4%2.73k ± 4%−3.95%(p=0.002 n=10+9)
 

github-actions[bot] avatar Sep 26 '22 20:09 github-actions[bot]

Codecov Report

Merging #3240 (f71f407) into master (a7a69d2) will decrease coverage by 1.18%. The diff coverage is 77.46%.

@@            Coverage Diff             @@
##           master    #3240      +/-   ##
==========================================
- Coverage   55.16%   53.98%   -1.19%     
==========================================
  Files         736      589     -147     
  Lines       67164    50727   -16437     
==========================================
- Hits        37053    27384    -9669     
+ Misses      27072    21113    -5959     
+ Partials     3039     2230     -809     
Flag Coverage Δ
unittests 53.98% <77.46%> (-1.19%) :arrow_down:

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

Impacted Files Coverage Δ
module/chunks/chunkVerifier.go 69.46% <70.00%> (-0.12%) :arrow_down:
fvm/executionParameters.go 80.74% <71.42%> (-2.59%) :arrow_down:
fvm/fvm.go 69.16% <85.71%> (+3.42%) :arrow_up:
fvm/context.go 60.62% <100.00%> (+1.27%) :arrow_up:
insecure/corruptible/network.go 48.65% <0.00%> (-0.60%) :arrow_down:
engine/execution/computation/computer/computer.go
...ngine/consensus/approvals/aggregated_signatures.go
engine/access/rpc/backend/backend_block_headers.go
engine/access/rest/request/transaction.go
... and 148 more

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

codecov-commenter avatar Sep 28 '22 21:09 codecov-commenter

after discussion we decided to use state-replay cache to do cached state reads while keeping the original reg touch records.

Tonix517 avatar Oct 20 '22 03:10 Tonix517