Skip to content

Sovereign-Labs/riscv-cycle-tracer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tracer

  • The tracer binary makes use of goblin, capstone and rustc-demangle to disassemble the riscV ELF and build a symbol table
  • The execution trace for the rollup ELF is generated by running the demo-prover with the ROLLUP_TRACE environment variable set to the desired path
  • The command should be run from the sovereign root repo
BLOCKS=1 TXNS_PER_BLOCK=10 ROLLUP_TRACE=rollup.trace cargo bench --bench prover_bench --features bench
  • rollup.trace now contains the program counter values for the run of prover_bench (how many ever blocks, blobs and transactions we configured it for)
$ find . -name rollup.trace
./examples/demo-rollup/rollup.trace
  • The corresponding ELF used for the trace is found at
$ find . -name mock_da
./target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da
$ file ./target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da
./target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da: ELF 32-bit LSB executable, UCB RISC-V, soft-float ABI, version 1 (SYSV), statically linked, with debug_info, not stripped
  • Both the above files are passed as input to the tracer
  • cd into the tracer sub folder
$ cd utils/zk-cycle-utils/tracer/
$ cargo run --release -- --rollup-elf ../../../target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da --rollup-trace ../../../examples/demo-rollup/rollup.trace -h
    Finished release [optimized] target(s) in 0.09s
     Running `target/release/tracer --rollup-elf ../../../target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da --rollup-trace ../../../examples/demo-rollup/rollup.trace -h`
Usage: tracer [OPTIONS] --rollup-elf <ROLLUP_ELF> --rollup-trace <ROLLUP_TRACE>

Options:
  -t, --top <TOP>                      Include the "top" number of functions [default: 30]
      --no-stack-counts                Don't print stack aware instruction counts
      --no-raw-counts                  Don't print raw (stack un-aware) instruction counts
      --rollup-elf <ROLLUP_ELF>        Path to the riscv32 elf
      --rollup-trace <ROLLUP_TRACE>    Path to the rollup trace. File must be one u64 program counter per line
  -s, --strip-hashes                   Strip the hashes from the function name while printing
  -f, --function-name <FUNCTION_NAME>  Function name to target for getting stack counts
  -e, --exclude-view <EXCLUDE_VIEW>    Exclude functions matching these patterns from display usage: -e func1 -e func2 -e func3
  -h, --help                           Print help
  -V, --version                        Print version

$ 
  • Important note: The paths of rollup.trace and the mock_da ELF used need to be adjusted to be reachable from the tracer folder
elf: ../../../target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da
trace: ../../../examples/demo-rollup/rollup.trace
  • Running it with the minimum options produces 2 tables
$ cargo run --release -- --rollup-elf ../../../target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da --rollup-trace ../../../examples/demo-rollup/rollup.trace  
    Finished release [optimized] target(s) in 0.14s
     Running `target/release/tracer --rollup-elf ../../../target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da --rollup-trace ../../../examples/demo-rollup/rollup.trace`
  [00:00:07] [########################################] 11364536/11364536 (0s)                                                    

Total instructions in trace: 11364536


 Instruction counts considering call graph
+--------------------------------------------------------------------------------------------+-------------------+
| Function Name                                                                              | Instruction Count |
+============================================================================================+===================+
| __start                                                                                    | 12043541          |
+--------------------------------------------------------------------------------------------+-------------------+
| main                                                                                       | 12042478          |
+--------------------------------------------------------------------------------------------+-------------------+
| sov_modules_stf_blueprint::<impl                                                           | 10353814          |
| sov_rollup_interface::state_machine::stf::StateTransitionFunction<Vm,Da> for               |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>>::apply_slot::h97c58a |                   |
| f7db410f5f                                                                                 |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>::apply_blob::he0c919b | 6780985           |
| cb192ee1f                                                                                  |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| <sov_modules_api::default_signature::DefaultSignature as                                   | 6098836           |
| sov_modules_core::common::key::Signature>::verify::h4001d1ebfb6fbfa5                       |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| <curve25519_dalek::backend::serial::risc0::field::FieldElementR0 as                        | 2191143           |
| core::ops::arith::AddAssign<&curve25519_dalek::backend::serial::risc0::field::FieldElement |                   |
| R0>>::add_assign::h803b2e4d149c8486                                                        |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| curve25519_dalek::backend::serial::curve_models::ProjectivePoint::double::hec30a33dc70ebee | 2130578           |
| c                                                                                          |                   |
+--------------------------------------------------------------------------------------------+-------------------+
.
.
.
+--------------------------------------------------------------------------------------------+-------------------+


 Instruction counts ignoring call graph
+--------------------------------------------------------------------------------------------+-------------------+
| Function Name                                                                              | Instruction Count |
+============================================================================================+===================+
| <curve25519_dalek::backend::serial::risc0::field::FieldElementR0 as                        | 2128983           |
| core::ops::arith::AddAssign<&curve25519_dalek::backend::serial::risc0::field::FieldElement |                   |
| R0>>::add_assign::h803b2e4d149c8486                                                        |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| memcpy                                                                                     | 1780887           |
+--------------------------------------------------------------------------------------------+-------------------+
| serde::de::impls::<impl serde::de::Deserialize for                                         | 1584576           |
| alloc::vec::Vec<T>>::deserialize::hdea67e98bd7defc3                                        |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| <sov_modules_api::default_signature::DefaultSignature as                                   | 1226230           |
| sov_modules_core::common::key::Signature>::verify::h4001d1ebfb6fbfa5                       |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| sha2::sha256::compress256::h7aa33e4ad80197be                                               | 944318            |
+--------------------------------------------------------------------------------------------+-------------------+
| curve25519_dalek::backend::serial::curve_models::ProjectivePoint::double::hec30a33dc70ebee | 916777            |
| c                                                                                          |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| <T as jmt::SimpleHasher>::finalize::h16335de3188b5a1f                                      | 444077            |
+--------------------------------------------------------------------------------------------+-------------------+
| sha2::sha512::compress512::hf06958a07bd42930                                               | 313566            |
+--------------------------------------------------------------------------------------------+-------------------+
.
.
.
+--------------------------------------------------------------------------------------------+-------------------+
  • The complete tables have been omitted for readability

  • By default the tracer only picks the top 30 functions by count (This can be changed with a flag)

  • Instruction counts ignoring call graph only considers the ELF and not the trace

  • Instruction counts considering call graph analyzes the trace by using the symbol tables built from analyzing the ELF

  • The hashes mangled at the end of the function names can be removed using -s, --strip-hashes option (only for readability). For the next section regarding detailed stack traces however, we should provide the hash as well

  • In order to see the detailed stack trace of a single function, it can be passed as an argument. Lets say we're interested in this particular function

<sov_modules_api::default_signature::DefaultSignature as sov_modules_core::common::key::Signature>::verify::h4001d1ebfb6fbfa5
  • It can be passed in as an argument using -f. Additionally, if we don't want to see the two primary tables, we can exclude them using --no-raw-counts --no-stack-counts
$ cargo run --release -- --rollup-elf ../../../target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da --rollup-trace ../../../examples/demo-rollup/rollup.trace -f "<sov_modules_api::default_signature::DefaultSignature as sov_modules_core::common::key::Signature>::verify::h4001d1ebfb6fbfa5" --no-raw-counts --no-stack-counts
  [00:00:09] [########################################] 11364536/11364536 (0s)                                                    

Total instructions in trace: 11364536


 Stack patterns for function '<sov_modules_api::default_signature::DefaultSignature as sov_modules_core::common::key::Signature>::verify::h4001d1ebfb6fbfa5' 
+--------------------------------------------------------------------------------------------+-------------------+
| Function Stack                                                                             | Instruction Count |
+============================================================================================+===================+
| (1) <sov_modules_api::default_signature::DefaultSignature as                               | 6098836           |
| sov_modules_core::common::key::Signature>::verify::h4001d1ebfb6fbfa5                       |                   |
| (2)                                                                                        |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>::apply_blob::he0c919b |                   |
| cb192ee1f                                                                                  |                   |
| (3) sov_modules_stf_blueprint::<impl                                                       |                   |
| sov_rollup_interface::state_machine::stf::StateTransitionFunction<Vm,Da> for               |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>>::apply_slot::h97c58a |                   |
| f7db410f5f                                                                                 |                   |
| (4) main                                                                                   |                   |
| (5) __start                                                                                |                   |
+--------------------------------------------------------------------------------------------+-------------------+
  • If we want to try the memcpy function, since its used in a lot more places
cargo run --release -- --rollup-elf ../../../target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da --rollup-trace ../../../examples/demo-rollup/rollup.trace -f "memcpy" --no-raw-counts --no-stack-counts
    Finished release [optimized] target(s) in 0.15s
     Running `target/release/tracer --rollup-elf ../../../target/riscv-guest/riscv32im-risc0-zkvm-elf/release/mock_da --rollup-trace ../../../examples/demo-rollup/rollup.trace -f memcpy --no-raw-counts --no-stack-counts`
  [00:00:07] [########################################] 11364536/11364536 (0s)                                                    

Total instructions in trace: 11364536


 Stack patterns for function 'memcpy' 
+--------------------------------------------------------------------------------------------+-------------------+
| Function Stack                                                                             | Instruction Count |
+============================================================================================+===================+
| (1) memcpy                                                                                 | 506613            |
| (2) <sov_modules_api::default_signature::DefaultSignature as                               |                   |
| sov_modules_core::common::key::Signature>::verify::h4001d1ebfb6fbfa5                       |                   |
| (3)                                                                                        |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>::apply_blob::he0c919b |                   |
| cb192ee1f                                                                                  |                   |
| (4) sov_modules_stf_blueprint::<impl                                                       |                   |
| sov_rollup_interface::state_machine::stf::StateTransitionFunction<Vm,Da> for               |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>>::apply_slot::h97c58a |                   |
| f7db410f5f                                                                                 |                   |
| (5) main                                                                                   |                   |
| (6) __start                                                                                |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| (1) memcpy                                                                                 | 193956            |
| (2) jmt::types::proof::SparseMerkleNode::hash::hdd0011ca380b940b                           |                   |
| (3) jmt::types::proof::definition::SparseMerkleProof<H>::root_hash::h7ad79865c71ff315      |                   |
| (4) sov_modules_stf_blueprint::<impl                                                       |                   |
| sov_rollup_interface::state_machine::stf::StateTransitionFunction<Vm,Da> for               |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>>::apply_slot::h97c58a |                   |
| f7db410f5f                                                                                 |                   |
| (5) main                                                                                   |                   |
| (6) __start                                                                                |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| (1) memcpy                                                                                 | 137459            |
| (2) jmt::types::proof::SparseMerkleInternalNode::hash::h45df4fe2c5f50a03                   |                   |
| (3) jmt::types::proof::definition::SparseMerkleProof<H>::root_hash::h7ad79865c71ff315      |                   |
| (4) sov_modules_stf_blueprint::<impl                                                       |                   |
| sov_rollup_interface::state_machine::stf::StateTransitionFunction<Vm,Da> for               |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>>::apply_slot::h97c58a |                   |
| f7db410f5f                                                                                 |                   |
| (5) main                                                                                   |                   |
| (6) __start                                                                                |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| (1) memcpy                                                                                 | 132932            |
| (2) <jmt::types::proof::definition::SparseMerkleProof<H> as                                |                   |
| borsh::de::BorshDeserialize>::deserialize_reader::h0ba54d52b47c6c43                        |                   |
| (3) sov_modules_stf_blueprint::<impl                                                       |                   |
| sov_rollup_interface::state_machine::stf::StateTransitionFunction<Vm,Da> for               |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>>::apply_slot::h97c58a |                   |
| f7db410f5f                                                                                 |                   |
| (4) main                                                                                   |                   |
| (5) __start                                                                                |                   |
+--------------------------------------------------------------------------------------------+-------------------+
| (1) memcpy                                                                                 | 98317             |
| (2) jmt::types::proof::SparseMerkleNode::hash::hdd0011ca380b940b                           |                   |
| (3)                                                                                        |                   |
| jmt::types::proof::definition::SparseMerkleProof<H>::verify_nonexistence::h9f642ad03e92295 |                   |
| 1                                                                                          |                   |
| (4) sov_modules_stf_blueprint::<impl                                                       |                   |
| sov_rollup_interface::state_machine::stf::StateTransitionFunction<Vm,Da> for               |                   |
| sov_modules_stf_blueprint::stf_blueprint::StfBlueprint<C,Da,Vm,RT,K>>::apply_slot::h97c58a |                   |
| f7db410f5f                                                                                 |                   |
| (5) main                                                                                   |                   |
| (6) __start                                                                                |                   |
+--------------------------------------------------------------------------------------------+-------------------+
  • The above call prints all the places memcpy is used in descending order of the cycles (There are more tables since memcpy is used in a lot of functions, but excluded for readability)

NOTES and TODO

  • This uses the mock_da ELF because prover_bench.rs runs using it, but the tracer can be used with any risc0 ELF and the trace that it produces
  • The ELF used to produce the trace must be the same pairing used with the tracer. Recompiling the ELF and using an older trace would cause inconsistencies in the symbol table and thus produce garbage
    • TODO: We could store a hash of the ELF in the trace and use that to exit early instead of producing garbage
  • mock_da is built using the flags from Cargo.toml.
    • TODO: We might see different results if we build it in non-release mode so that the compiler won't do any aggressive inlining
    • This could possibly help us get a more accurate representation of the stack traces that would directly map to our code
  • Running in --release mode speeds up the tracer since it performs a lot of analyzsis (analyzing larger workloads can be slow if not used in --release)
  • TODO: profiler needs to be added to CI as well. Fortunately, this can be merged with the part where prover_bench is already run (Just passing ROLLUP_TRACE so that the bench also produces the trace) as an additional step, so it should only take a minute or two extra

About

A profiler and CPU cycle counter for Sovereign SDK applications

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Languages