From b197dcc0df783485e67f001e9fe0e7a9ad891393 Mon Sep 17 00:00:00 2001 From: Wojciech Szymczyk Date: Mon, 14 Oct 2024 10:03:44 +0200 Subject: [PATCH 1/5] Treat syscalls as nodes --- crates/cairo-profiler/Cargo.toml | 3 + .../versioned_constants_0_13_2_1.json | 633 ++++++++++++++++++ crates/cairo-profiler/src/main.rs | 8 + crates/cairo-profiler/src/profile_builder.rs | 12 +- crates/cairo-profiler/src/trace_reader.rs | 21 +- .../cairo-profiler/src/trace_reader/sample.rs | 17 +- .../src/trace_reader/syscall.rs | 89 +++ crates/trace-data/src/lib.rs | 5 + 8 files changed, 769 insertions(+), 19 deletions(-) create mode 100644 crates/cairo-profiler/resources/versioned_constants_0_13_2_1.json create mode 100644 crates/cairo-profiler/src/trace_reader/syscall.rs diff --git a/crates/cairo-profiler/Cargo.toml b/crates/cairo-profiler/Cargo.toml index 7b12ebb..d524125 100644 --- a/crates/cairo-profiler/Cargo.toml +++ b/crates/cairo-profiler/Cargo.toml @@ -3,6 +3,9 @@ name = "cairo-profiler" version.workspace = true edition.workspace = true +[package.metadata] +include = ["resources/*"] + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/cairo-profiler/resources/versioned_constants_0_13_2_1.json b/crates/cairo-profiler/resources/versioned_constants_0_13_2_1.json new file mode 100644 index 0000000..9d90171 --- /dev/null +++ b/crates/cairo-profiler/resources/versioned_constants_0_13_2_1.json @@ -0,0 +1,633 @@ +{ + "tx_event_limits": { + "max_data_length": 300, + "max_keys_length": 50, + "max_n_emitted_events": 1000 + }, + "gateway": { + "max_calldata_length": 5000, + "max_contract_bytecode_size": 81920 + }, + "invoke_tx_max_n_steps": 10000000, + "deprecated_l2_resource_gas_costs": { + "gas_per_data_felt": [ + 128, + 1000 + ], + "event_key_factor": [ + 2, + 1 + ], + "gas_per_code_byte": [ + 32, + 1000 + ] + }, + "archival_data_gas_costs": { + "gas_per_data_felt": [ + 5120, + 1 + ], + "event_key_factor": [ + 2, + 1 + ], + "gas_per_code_byte": [ + 1280, + 1 + ] + }, + "disable_cairo0_redeclaration": true, + "max_recursion_depth": 50, + "enable_reverts": false, + "segment_arena_cells": false, + "os_constants": { + "block_hash_contract_address": 1, + "call_contract_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "constructor_entry_point_selector": "0x28ffe4ff0f226a9107253e17a904099aa4f63a02a5621de0576e5aa71bc5194", + "default_entry_point_selector": 0, + "deploy_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 200, + "syscall_base_gas_cost": 1 + }, + "emit_event_gas_cost": { + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "entry_point_gas_cost": { + "entry_point_initial_budget": 1, + "step_gas_cost": 500 + }, + "entry_point_initial_budget": { + "step_gas_cost": 100 + }, + "entry_point_type_constructor": 2, + "entry_point_type_external": 0, + "entry_point_type_l1_handler": 1, + "error_block_number_out_of_range": "Block number out of range", + "error_invalid_input_len": "Invalid input length", + "error_invalid_argument": "Invalid argument", + "error_out_of_gas": "Out of gas", + "error_entry_point_failed": "ENTRYPOINT_FAILED", + "error_entry_point_not_found": "ENTRYPOINT_NOT_FOUND", + "execute_entry_point_selector": "0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad", + "fee_transfer_gas_cost": { + "entry_point_gas_cost": 1, + "step_gas_cost": 100 + }, + "get_block_hash_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "get_execution_info_gas_cost": { + "step_gas_cost": 10, + "syscall_base_gas_cost": 1 + }, + "default_initial_gas_cost": { + "step_gas_cost": 100000000 + }, + "keccak_gas_cost": { + "syscall_base_gas_cost": 1 + }, + "keccak_round_cost_gas_cost": 180000, + "l1_gas": "L1_GAS", + "l1_gas_index": 0, + "l1_handler_version": 0, + "l2_gas": "L2_GAS", + "l2_gas_index": 1, + "library_call_gas_cost": { + "call_contract_gas_cost": 1 + }, + "sha256_process_block_gas_cost": { + "step_gas_cost": 1852, + "range_check_gas_cost": 65, + "bitwise_builtin_gas_cost": 1115, + "syscall_base_gas_cost": 1 + }, + "memory_hole_gas_cost": 10, + "nop_entry_point_offset": -1, + "range_check_gas_cost": 70, + "pedersen_gas_cost": 0, + "bitwise_builtin_gas_cost": 594, + "ecop_gas_cost": 0, + "poseidon_gas_cost": 0, + "add_mod_gas_cost": 0, + "mul_mod_gas_cost": 0, + "replace_class_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "secp256k1_add_gas_cost": { + "range_check_gas_cost": 29, + "step_gas_cost": 406 + }, + "secp256k1_get_point_from_x_gas_cost": { + "memory_hole_gas_cost": 20, + "range_check_gas_cost": 30, + "step_gas_cost": 391 + }, + "secp256k1_get_xy_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 11, + "step_gas_cost": 239 + }, + "secp256k1_mul_gas_cost": { + "memory_hole_gas_cost": 2, + "range_check_gas_cost": 7045, + "step_gas_cost": 76501 + }, + "secp256k1_new_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 35, + "step_gas_cost": 475 + }, + "secp256r1_add_gas_cost": { + "range_check_gas_cost": 57, + "step_gas_cost": 589 + }, + "secp256r1_get_point_from_x_gas_cost": { + "memory_hole_gas_cost": 20, + "range_check_gas_cost": 44, + "step_gas_cost": 510 + }, + "secp256r1_get_xy_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 11, + "step_gas_cost": 241 + }, + "secp256r1_mul_gas_cost": { + "memory_hole_gas_cost": 2, + "range_check_gas_cost": 13961, + "step_gas_cost": 125340 + }, + "secp256r1_new_gas_cost": { + "memory_hole_gas_cost": 40, + "range_check_gas_cost": 49, + "step_gas_cost": 594 + }, + "send_message_to_l1_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "sierra_array_len_bound": 4294967296, + "step_gas_cost": 100, + "storage_read_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "storage_write_gas_cost": { + "step_gas_cost": 50, + "syscall_base_gas_cost": 1 + }, + "stored_block_hash_buffer": 10, + "syscall_base_gas_cost": { + "step_gas_cost": 100 + }, + "transaction_gas_cost": { + "entry_point_gas_cost": 2, + "fee_transfer_gas_cost": 1, + "step_gas_cost": 100 + }, + "transfer_entry_point_selector": "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", + "validate_declare_entry_point_selector": "0x289da278a8dc833409cabfdad1581e8e7d40e42dcaed693fa4008dcdb4963b3", + "validate_deploy_entry_point_selector": "0x36fcbf06cd96843058359e1a75928beacfac10727dab22a3972f0af8aa92895", + "validate_entry_point_selector": "0x162da33a4585851fe8d3af3c2a9c60b557814e221e0d4f30ff0b2189d9c7775", + "validate_rounding_consts": { + "validate_block_number_rounding": 100, + "validate_timestamp_rounding": 3600 + }, + "validated": "VALID" + }, + "os_resources": { + "execute_syscalls": { + "CallContract": { + "n_steps": 827, + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0 + }, + "DelegateCall": { + "n_steps": 713, + "builtin_instance_counter": { + "range_check_builtin": 19 + }, + "n_memory_holes": 0 + }, + "DelegateL1Handler": { + "n_steps": 692, + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0 + }, + "Deploy": { + "n_steps": 1097, + "builtin_instance_counter": { + "pedersen_builtin": 7, + "range_check_builtin": 18 + }, + "n_memory_holes": 0 + }, + "EmitEvent": { + "n_steps": 61, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetBlockHash": { + "n_steps": 104, + "builtin_instance_counter": { + "range_check_builtin": 2 + }, + "n_memory_holes": 0 + }, + "GetBlockNumber": { + "n_steps": 40, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "GetBlockTimestamp": { + "n_steps": 38, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "GetCallerAddress": { + "n_steps": 64, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetContractAddress": { + "n_steps": 64, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetExecutionInfo": { + "n_steps": 64, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetSequencerAddress": { + "n_steps": 34, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "GetTxInfo": { + "n_steps": 64, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetTxSignature": { + "n_steps": 44, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "Keccak": { + "n_steps": 381, + "builtin_instance_counter": { + "bitwise_builtin": 6, + "keccak_builtin": 1, + "range_check_builtin": 56 + }, + "n_memory_holes": 0 + }, + "LibraryCall": { + "n_steps": 818, + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0 + }, + "LibraryCallL1Handler": { + "n_steps": 659, + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0 + }, + "ReplaceClass": { + "n_steps": 98, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "Secp256k1Add": { + "n_steps": 410, + "builtin_instance_counter": { + "range_check_builtin": 29 + }, + "n_memory_holes": 0 + }, + "Secp256k1GetPointFromX": { + "n_steps": 395, + "builtin_instance_counter": { + "range_check_builtin": 30 + }, + "n_memory_holes": 0 + }, + "Secp256k1GetXy": { + "n_steps": 207, + "builtin_instance_counter": { + "range_check_builtin": 11 + }, + "n_memory_holes": 0 + }, + "Secp256k1Mul": { + "n_steps": 76505, + "builtin_instance_counter": { + "range_check_builtin": 7045 + }, + "n_memory_holes": 0 + }, + "Secp256k1New": { + "n_steps": 461, + "builtin_instance_counter": { + "range_check_builtin": 35 + }, + "n_memory_holes": 0 + }, + "Secp256r1Add": { + "n_steps": 593, + "builtin_instance_counter": { + "range_check_builtin": 57 + }, + "n_memory_holes": 0 + }, + "Secp256r1GetPointFromX": { + "n_steps": 514, + "builtin_instance_counter": { + "range_check_builtin": 44 + }, + "n_memory_holes": 0 + }, + "Secp256r1GetXy": { + "n_steps": 209, + "builtin_instance_counter": { + "range_check_builtin": 11 + }, + "n_memory_holes": 0 + }, + "Secp256r1Mul": { + "n_steps": 125344, + "builtin_instance_counter": { + "range_check_builtin": 13961 + }, + "n_memory_holes": 0 + }, + "Secp256r1New": { + "n_steps": 580, + "builtin_instance_counter": { + "range_check_builtin": 49 + }, + "n_memory_holes": 0 + }, + "SendMessageToL1": { + "n_steps": 141, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "Sha256ProcessBlock": { + "n_steps": 1855, + "builtin_instance_counter": { + "range_check_builtin": 65, + "bitwise_builtin": 1115 + }, + "n_memory_holes": 0 + }, + "StorageRead": { + "n_steps": 87, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "StorageWrite": { + "n_steps": 89, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + } + }, + "execute_txs_inner": { + "Declare": { + "deprecated_resources": { + "constant": { + "n_steps": 2973, + "builtin_instance_counter": { + "pedersen_builtin": 16, + "range_check_builtin": 53 + }, + "n_memory_holes": 0 + }, + "calldata_factor": { + "n_steps": 0, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + } + }, + "resources": { + "constant": { + "n_steps": 3079, + "builtin_instance_counter": { + "pedersen_builtin": 4, + "range_check_builtin": 58, + "poseidon_builtin": 10 + }, + "n_memory_holes": 0 + }, + "calldata_factor": { + "n_steps": 0, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + } + } + }, + "DeployAccount": { + "deprecated_resources": { + "constant": { + "n_steps": 4015, + "builtin_instance_counter": { + "pedersen_builtin": 23, + "range_check_builtin": 72 + }, + "n_memory_holes": 0 + }, + "calldata_factor": { + "n_steps": 21, + "builtin_instance_counter": { + "pedersen_builtin": 2 + }, + "n_memory_holes": 0 + } + }, + "resources": { + "constant": { + "n_steps": 4137, + "builtin_instance_counter": { + "pedersen_builtin": 11, + "range_check_builtin": 77, + "poseidon_builtin": 10 + }, + "n_memory_holes": 0 + }, + "calldata_factor": { + "n_steps": 21, + "builtin_instance_counter": { + "pedersen_builtin": 2 + }, + "n_memory_holes": 0 + } + } + }, + "InvokeFunction": { + "deprecated_resources": { + "constant": { + "n_steps": 3763, + "builtin_instance_counter": { + "pedersen_builtin": 14, + "range_check_builtin": 69 + }, + "n_memory_holes": 0 + }, + "calldata_factor": { + "n_steps": 8, + "builtin_instance_counter": { + "pedersen_builtin": 1 + }, + "n_memory_holes": 0 + } + }, + "resources": { + "constant": { + "n_steps": 3904, + "builtin_instance_counter": { + "pedersen_builtin": 4, + "range_check_builtin": 74, + "poseidon_builtin": 11 + }, + "n_memory_holes": 0 + }, + "calldata_factor": { + "n_steps": 8, + "builtin_instance_counter": { + "pedersen_builtin": 1 + }, + "n_memory_holes": 0 + } + } + }, + "L1Handler": { + "deprecated_resources": { + "constant": { + "n_steps": 1233, + "builtin_instance_counter": { + "pedersen_builtin": 11, + "range_check_builtin": 16 + }, + "n_memory_holes": 0 + }, + "calldata_factor": { + "n_steps": 13, + "builtin_instance_counter": { + "pedersen_builtin": 1 + }, + "n_memory_holes": 0 + } + }, + "resources": { + "constant": { + "n_steps": 0, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "calldata_factor": { + "n_steps": 13, + "builtin_instance_counter": { + "pedersen_builtin": 1 + }, + "n_memory_holes": 0 + } + } + } + }, + "compute_os_kzg_commitment_info": { + "n_steps": 113, + "builtin_instance_counter": { + "range_check_builtin": 17 + }, + "n_memory_holes": 0 + } + }, + "validate_max_n_steps": 1000000, + "min_compiler_version_for_sierra_gas": "2.8.0", + "vm_resource_fee_cost": { + "builtins": { + "add_mod_builtin": [ + 4, + 100 + ], + "bitwise_builtin": [ + 16, + 100 + ], + "ec_op_builtin": [ + 256, + 100 + ], + "ecdsa_builtin": [ + 512, + 100 + ], + "keccak_builtin": [ + 512, + 100 + ], + "mul_mod_builtin": [ + 4, + 100 + ], + "output_builtin": [ + 0, + 1 + ], + "pedersen_builtin": [ + 8, + 100 + ], + "poseidon_builtin": [ + 8, + 100 + ], + "range_check_builtin": [ + 4, + 100 + ], + "range_check96_builtin": [ + 4, + 100 + ] + }, + "n_steps": [ + 25, + 10000 + ] + } +} diff --git a/crates/cairo-profiler/src/main.rs b/crates/cairo-profiler/src/main.rs index 49693aa..bef09ad 100644 --- a/crates/cairo-profiler/src/main.rs +++ b/crates/cairo-profiler/src/main.rs @@ -6,6 +6,7 @@ use std::{ use crate::profiler_config::ProfilerConfig; use crate::sierra_loader::collect_and_compile_all_sierra_programs; use crate::trace_reader::collect_samples_from_trace; +use crate::trace_reader::syscall::read_and_parse_versioned_constants_file; use anyhow::{Context, Result}; use bytes::{Buf, BytesMut}; use camino::Utf8PathBuf; @@ -49,6 +50,9 @@ struct Cli { /// `unstable-add-statements-functions-debug-info = true` in `[cairo]` section of Scarb.toml. #[arg(long)] show_inlined_functions: bool, + + #[arg(long)] + versioned_constants_path: Option, } fn main() -> Result<()> { @@ -72,10 +76,14 @@ fn main() -> Result<()> { ); } + let os_resources_map = read_and_parse_versioned_constants_file(&cli.versioned_constants_path) + .expect("Failed to parse os_resources_map from a file"); + let samples = collect_samples_from_trace( &serialized_trace, &compiled_artifacts_cache, &profiler_config, + &os_resources_map, )?; let profile = build_profile(&samples); diff --git a/crates/cairo-profiler/src/profile_builder.rs b/crates/cairo-profiler/src/profile_builder.rs index 54664b0..f7f57fb 100644 --- a/crates/cairo-profiler/src/profile_builder.rs +++ b/crates/cairo-profiler/src/profile_builder.rs @@ -11,6 +11,7 @@ use std::collections::{HashMap, HashSet}; pub use perftools::profiles as pprof; use crate::trace_reader::function_name::FunctionName; +use crate::trace_reader::sample::InternalFunctionCall::Syscall; use crate::trace_reader::sample::{ FunctionCall, InternalFunctionCall, MeasurementUnit, MeasurementValue, Sample, }; @@ -85,7 +86,9 @@ impl ProfilerContext { let mut current_function_stack_start_index = 0; for (index, function) in call_stack.iter().enumerate() { match function { - FunctionCall::InternalFunctionCall(InternalFunctionCall::NonInlined(_)) + FunctionCall::InternalFunctionCall( + InternalFunctionCall::NonInlined(_) | Syscall(_), + ) | FunctionCall::EntrypointCall(_) => { if index != 0 { function_stacks_indexes @@ -104,7 +107,7 @@ impl ProfilerContext { locations_ids.push(LocationId(location.id)); } else { let mut location = match &function_stack[0] { - FunctionCall::EntrypointCall(function_name) | FunctionCall::InternalFunctionCall(InternalFunctionCall::NonInlined(function_name)) => { + FunctionCall::EntrypointCall(function_name) | FunctionCall::InternalFunctionCall(InternalFunctionCall::NonInlined(function_name) | Syscall(function_name)) => { let line = pprof::Line { function_id: self.function_id(function_name).into(), line: 0, @@ -132,8 +135,9 @@ impl ProfilerContext { location.line.push(line); } FunctionCall::EntrypointCall(_) - | FunctionCall::InternalFunctionCall(InternalFunctionCall::NonInlined(_)) => - { + | FunctionCall::InternalFunctionCall( + InternalFunctionCall::NonInlined(_) | Syscall(_), + ) => { unreachable!("Only first function in a function stack corresponding to a single location can be not inlined") } } diff --git a/crates/cairo-profiler/src/trace_reader.rs b/crates/cairo-profiler/src/trace_reader.rs index 8cbd6e3..0818563 100644 --- a/crates/cairo-profiler/src/trace_reader.rs +++ b/crates/cairo-profiler/src/trace_reader.rs @@ -7,17 +7,20 @@ use crate::trace_reader::function_name::FunctionName; use crate::trace_reader::function_trace_builder::collect_function_level_profiling_info; use crate::trace_reader::sample::{FunctionCall, Sample}; +use crate::trace_reader::syscall::collect_syscall_sample; -use trace_data::{CallTrace, CallTraceNode, ExecutionResources}; +use trace_data::{CallTrace, CallTraceNode, ExecutionResources, OsResources}; pub mod function_name; mod function_trace_builder; pub mod sample; +pub mod syscall; pub fn collect_samples_from_trace( trace: &CallTrace, compiled_artifacts_cache: &CompiledArtifactsCache, profiler_config: &ProfilerConfig, + os_resources_map: &OsResources, ) -> Result> { let mut samples = vec![]; let mut current_entrypoint_call_stack = vec![]; @@ -28,6 +31,7 @@ pub fn collect_samples_from_trace( trace, compiled_artifacts_cache, profiler_config, + os_resources_map, )?; Ok(samples) @@ -39,6 +43,7 @@ fn collect_samples<'a>( trace: &'a CallTrace, compiled_artifacts_cache: &CompiledArtifactsCache, profiler_config: &ProfilerConfig, + os_resources_map: &OsResources, ) -> Result<&'a ExecutionResources> { current_entrypoint_call_stack.push(FunctionCall::EntrypointCall( FunctionName::from_entry_point_params( @@ -103,6 +108,7 @@ fn collect_samples<'a>( sub_trace, compiled_artifacts_cache, profiler_config, + &os_resources_map, )?; } } @@ -119,6 +125,19 @@ fn collect_samples<'a>( &trace.used_l1_resources, )); + call_resources + .syscall_counter + .iter() + .filter(|(_, count)| **count != 0) + .for_each(|(syscall, count)| { + samples.push(collect_syscall_sample( + current_entrypoint_call_stack.clone(), + syscall, + count, + os_resources_map, + )); + }); + current_entrypoint_call_stack.pop(); Ok(&trace.cumulative_resources) diff --git a/crates/cairo-profiler/src/trace_reader/sample.rs b/crates/cairo-profiler/src/trace_reader/sample.rs index 8894303..ee0841a 100644 --- a/crates/cairo-profiler/src/trace_reader/sample.rs +++ b/crates/cairo-profiler/src/trace_reader/sample.rs @@ -28,13 +28,15 @@ impl FunctionCall { pub enum InternalFunctionCall { Inlined(FunctionName), NonInlined(FunctionName), + Syscall(FunctionName), } impl InternalFunctionCall { pub fn function_name(&self) -> &FunctionName { match self { InternalFunctionCall::Inlined(function_name) - | InternalFunctionCall::NonInlined(function_name) => function_name, + | InternalFunctionCall::NonInlined(function_name) + | InternalFunctionCall::Syscall(function_name) => function_name, } } } @@ -82,19 +84,6 @@ impl Sample { ); } - let syscall_counter_with_string: Vec<_> = resources - .syscall_counter - .iter() - .map(|(syscall, count)| (format!("{syscall:?}"), *count)) - .collect(); - for (syscall, count) in &syscall_counter_with_string { - assert!(!measurements.contains_key(&MeasurementUnit::from(syscall.to_string()))); - measurements.insert( - MeasurementUnit::from(syscall.to_string()), - MeasurementValue(i64::try_from(*count).unwrap()), - ); - } - assert!( !measurements.contains_key(&MeasurementUnit::from("l2_l1_message_sizes".to_string())) ); diff --git a/crates/cairo-profiler/src/trace_reader/syscall.rs b/crates/cairo-profiler/src/trace_reader/syscall.rs new file mode 100644 index 0000000..15aa07c --- /dev/null +++ b/crates/cairo-profiler/src/trace_reader/syscall.rs @@ -0,0 +1,89 @@ +use crate::trace_reader::function_name::FunctionName; +use crate::trace_reader::sample::InternalFunctionCall::Syscall; +use crate::trace_reader::sample::{FunctionCall, MeasurementUnit, MeasurementValue, Sample}; +use anyhow::Result; +use camino::Utf8PathBuf; +use serde_json::{from_str, from_value, Value}; +use std::fs; +use trace_data::{DeprecatedSyscallSelector, OsResources}; + +pub fn collect_syscall_sample( + mut call_stack: Vec, + syscall: &DeprecatedSyscallSelector, + count: &usize, + os_resources_map: &OsResources, +) -> Sample { + call_stack.push(FunctionCall::InternalFunctionCall(Syscall(FunctionName( + format!("syscall: {syscall:?}"), + )))); + let resources = os_resources_map + .execute_syscalls + .get(syscall) + .expect("Failed to find syscall in resources map"); + Sample { + call_stack, + measurements: { + let mut measurements = vec![ + ( + MeasurementUnit::from("calls".to_string()), + MeasurementValue( + (*count) + .try_into() + .expect("overflow while converting to i64"), + ), + ), + ( + MeasurementUnit::from("steps".to_string()), + MeasurementValue( + resources + .n_steps + .checked_mul(*count) + .expect("multiplication overflow") + .try_into() + .expect("overflow while converting to i64"), + ), + ), + ( + MeasurementUnit::from("memory_holes".to_string()), + MeasurementValue( + resources + .n_memory_holes + .checked_mul(*count) + .expect("multiplication overflow") + .try_into() + .expect("overflow while converting to i64"), + ), + ), + ]; + + for (builtin, b_count) in &resources.builtin_instance_counter { + measurements.push(( + MeasurementUnit::from(builtin.to_string()), + MeasurementValue( + b_count + .checked_mul(*count) + .expect("multiplication overflow") + .try_into() + .expect("overflow while converting to i64"), + ), + )); + } + + measurements.into_iter().collect() + }, + } +} + +pub fn read_and_parse_versioned_constants_file(path: &Option) -> Result { + let file_content = match path { + Some(path) => fs::read_to_string(path)?, + // include_str requires a string literal + None => include_str!("../../resources/versioned_constants_0_13_2_1.json").to_string(), + }; + let json_value: Value = from_str(&file_content)?; + let parsed_resources = json_value + .get("os_resources") + .expect("Field 'os_resources' not found in versioned constants file"); + let os_resources: OsResources = from_value(parsed_resources.clone())?; + Ok(os_resources) +} diff --git a/crates/trace-data/src/lib.rs b/crates/trace-data/src/lib.rs index cdaa706..9d83080 100644 --- a/crates/trace-data/src/lib.rs +++ b/crates/trace-data/src/lib.rs @@ -213,3 +213,8 @@ impl ExecutionResources { pub struct L1Resources { pub l2_l1_message_sizes: Vec, } + +#[derive(Debug, Serialize, Deserialize)] +pub struct OsResources { + pub execute_syscalls: HashMap, +} From 265db610cb219cb6ea31d231b1a2ca53f9ac01ce Mon Sep 17 00:00:00 2001 From: Wojciech Szymczyk Date: Mon, 14 Oct 2024 10:16:18 +0200 Subject: [PATCH 2/5] Add simple test --- .../tests/data/test_versioned_constants.json | 226 ++++++++++++++++++ crates/cairo-profiler/tests/e2e.rs | 1 + 2 files changed, 227 insertions(+) create mode 100644 crates/cairo-profiler/tests/data/test_versioned_constants.json diff --git a/crates/cairo-profiler/tests/data/test_versioned_constants.json b/crates/cairo-profiler/tests/data/test_versioned_constants.json new file mode 100644 index 0000000..afd0a95 --- /dev/null +++ b/crates/cairo-profiler/tests/data/test_versioned_constants.json @@ -0,0 +1,226 @@ +{ + "os_resources": { + "execute_syscalls": { + "CallContract": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0 + }, + "DelegateCall": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 19 + }, + "n_memory_holes": 0 + }, + "DelegateL1Handler": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0 + }, + "Deploy": { + "n_steps": 10, + "builtin_instance_counter": { + "pedersen_builtin": 7, + "range_check_builtin": 18 + }, + "n_memory_holes": 0 + }, + "EmitEvent": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetBlockHash": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 2 + }, + "n_memory_holes": 0 + }, + "GetBlockNumber": { + "n_steps": 10, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "GetBlockTimestamp": { + "n_steps": 10, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "GetCallerAddress": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetContractAddress": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetExecutionInfo": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetSequencerAddress": { + "n_steps": 10, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "GetTxInfo": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "GetTxSignature": { + "n_steps": 10, + "builtin_instance_counter": {}, + "n_memory_holes": 0 + }, + "Keccak": { + "n_steps": 10, + "builtin_instance_counter": { + "bitwise_builtin": 6, + "keccak_builtin": 1, + "range_check_builtin": 56 + }, + "n_memory_holes": 0 + }, + "LibraryCall": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0 + }, + "LibraryCallL1Handler": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 15 + }, + "n_memory_holes": 0 + }, + "ReplaceClass": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "Secp256k1Add": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 29 + }, + "n_memory_holes": 0 + }, + "Secp256k1GetPointFromX": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 30 + }, + "n_memory_holes": 0 + }, + "Secp256k1GetXy": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 11 + }, + "n_memory_holes": 0 + }, + "Secp256k1Mul": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 7045 + }, + "n_memory_holes": 0 + }, + "Secp256k1New": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 35 + }, + "n_memory_holes": 0 + }, + "Secp256r1Add": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 57 + }, + "n_memory_holes": 0 + }, + "Secp256r1GetPointFromX": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 44 + }, + "n_memory_holes": 0 + }, + "Secp256r1GetXy": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 11 + }, + "n_memory_holes": 0 + }, + "Secp256r1Mul": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 13961 + }, + "n_memory_holes": 0 + }, + "Secp256r1New": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 49 + }, + "n_memory_holes": 0 + }, + "SendMessageToL1": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "Sha256ProcessBlock": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 65, + "bitwise_builtin": 1115 + }, + "n_memory_holes": 0 + }, + "StorageRead": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + }, + "StorageWrite": { + "n_steps": 10, + "builtin_instance_counter": { + "range_check_builtin": 1 + }, + "n_memory_holes": 0 + } + } + } +} diff --git a/crates/cairo-profiler/tests/e2e.rs b/crates/cairo-profiler/tests/e2e.rs index 1205e86..cf5a596 100644 --- a/crates/cairo-profiler/tests/e2e.rs +++ b/crates/cairo-profiler/tests/e2e.rs @@ -28,6 +28,7 @@ fn output_path() { #[test_case(&["call.json", "--max-function-stack-trace-depth", "5"]; "with max function trace depth")] #[test_case(&["call.json", "--show-details"]; "with details")] #[test_case(&["call.json"]; "without details")] +#[test_case(&["call.json", "--versioned-constants-path", "test_versioned_constants.json"]; "with custom versioned constants file")] fn simple_package(args: &[&str]) { let project_root = project_root::get_project_root().unwrap(); let temp_dir = assert_fs::TempDir::new().unwrap(); From 0d8e2f09a3e178dcfba35cff5fb9fec2d05d6ce0 Mon Sep 17 00:00:00 2001 From: Wojciech Szymczyk Date: Mon, 14 Oct 2024 10:25:26 +0200 Subject: [PATCH 3/5] Improve on msgs --- crates/cairo-profiler/src/main.rs | 2 +- .../cairo-profiler/src/trace_reader/syscall.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/cairo-profiler/src/main.rs b/crates/cairo-profiler/src/main.rs index bef09ad..aa0e0a8 100644 --- a/crates/cairo-profiler/src/main.rs +++ b/crates/cairo-profiler/src/main.rs @@ -77,7 +77,7 @@ fn main() -> Result<()> { } let os_resources_map = read_and_parse_versioned_constants_file(&cli.versioned_constants_path) - .expect("Failed to parse os_resources_map from a file"); + .expect("Failed to parse versioned constants file"); let samples = collect_samples_from_trace( &serialized_trace, diff --git a/crates/cairo-profiler/src/trace_reader/syscall.rs b/crates/cairo-profiler/src/trace_reader/syscall.rs index 15aa07c..57f218e 100644 --- a/crates/cairo-profiler/src/trace_reader/syscall.rs +++ b/crates/cairo-profiler/src/trace_reader/syscall.rs @@ -19,7 +19,7 @@ pub fn collect_syscall_sample( let resources = os_resources_map .execute_syscalls .get(syscall) - .expect("Failed to find syscall in resources map"); + .expect(format!("Missing syscall {syscall:?} from versioned constants file").as_str()); Sample { call_stack, measurements: { @@ -29,7 +29,7 @@ pub fn collect_syscall_sample( MeasurementValue( (*count) .try_into() - .expect("overflow while converting to i64"), + .expect("Overflow while converting to i64"), ), ), ( @@ -38,9 +38,9 @@ pub fn collect_syscall_sample( resources .n_steps .checked_mul(*count) - .expect("multiplication overflow") + .expect("Multiplication overflow") .try_into() - .expect("overflow while converting to i64"), + .expect("Overflow while converting to i64"), ), ), ( @@ -49,9 +49,9 @@ pub fn collect_syscall_sample( resources .n_memory_holes .checked_mul(*count) - .expect("multiplication overflow") + .expect("Multiplication overflow") .try_into() - .expect("overflow while converting to i64"), + .expect("Overflow while converting to i64"), ), ), ]; @@ -62,9 +62,9 @@ pub fn collect_syscall_sample( MeasurementValue( b_count .checked_mul(*count) - .expect("multiplication overflow") + .expect("Multiplication overflow") .try_into() - .expect("overflow while converting to i64"), + .expect("Overflow while converting to i64"), ), )); } From b2fbe813915a015a27c3c5d339f7dbbdcb659a38 Mon Sep 17 00:00:00 2001 From: Wojciech Szymczyk Date: Mon, 14 Oct 2024 10:30:08 +0200 Subject: [PATCH 4/5] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c58d0e2..be04f7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- show syscalls as nodes in trace tree rather than samples + ## [0.6.0] - 2024-08-22 - support for `sha256_process_block_syscall` From 0eda65dcb523d06d22b89a6cffe26f74ca075323 Mon Sep 17 00:00:00 2001 From: Wojciech Szymczyk Date: Mon, 14 Oct 2024 10:44:36 +0200 Subject: [PATCH 5/5] Fix linter --- crates/cairo-profiler/src/trace_reader.rs | 6 +++--- .../cairo-profiler/src/trace_reader/syscall.rs | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/cairo-profiler/src/trace_reader.rs b/crates/cairo-profiler/src/trace_reader.rs index 0818563..e7d6b3a 100644 --- a/crates/cairo-profiler/src/trace_reader.rs +++ b/crates/cairo-profiler/src/trace_reader.rs @@ -108,7 +108,7 @@ fn collect_samples<'a>( sub_trace, compiled_artifacts_cache, profiler_config, - &os_resources_map, + os_resources_map, )?; } } @@ -132,8 +132,8 @@ fn collect_samples<'a>( .for_each(|(syscall, count)| { samples.push(collect_syscall_sample( current_entrypoint_call_stack.clone(), - syscall, - count, + *syscall, + *count, os_resources_map, )); }); diff --git a/crates/cairo-profiler/src/trace_reader/syscall.rs b/crates/cairo-profiler/src/trace_reader/syscall.rs index 57f218e..5c0eeb6 100644 --- a/crates/cairo-profiler/src/trace_reader/syscall.rs +++ b/crates/cairo-profiler/src/trace_reader/syscall.rs @@ -9,8 +9,8 @@ use trace_data::{DeprecatedSyscallSelector, OsResources}; pub fn collect_syscall_sample( mut call_stack: Vec, - syscall: &DeprecatedSyscallSelector, - count: &usize, + syscall: DeprecatedSyscallSelector, + count: usize, os_resources_map: &OsResources, ) -> Sample { call_stack.push(FunctionCall::InternalFunctionCall(Syscall(FunctionName( @@ -18,8 +18,8 @@ pub fn collect_syscall_sample( )))); let resources = os_resources_map .execute_syscalls - .get(syscall) - .expect(format!("Missing syscall {syscall:?} from versioned constants file").as_str()); + .get(&syscall) + .unwrap_or_else(|| panic!("Missing syscall {syscall:?} from versioned constants file")); Sample { call_stack, measurements: { @@ -27,7 +27,7 @@ pub fn collect_syscall_sample( ( MeasurementUnit::from("calls".to_string()), MeasurementValue( - (*count) + (count) .try_into() .expect("Overflow while converting to i64"), ), @@ -37,7 +37,7 @@ pub fn collect_syscall_sample( MeasurementValue( resources .n_steps - .checked_mul(*count) + .checked_mul(count) .expect("Multiplication overflow") .try_into() .expect("Overflow while converting to i64"), @@ -48,7 +48,7 @@ pub fn collect_syscall_sample( MeasurementValue( resources .n_memory_holes - .checked_mul(*count) + .checked_mul(count) .expect("Multiplication overflow") .try_into() .expect("Overflow while converting to i64"), @@ -61,7 +61,7 @@ pub fn collect_syscall_sample( MeasurementUnit::from(builtin.to_string()), MeasurementValue( b_count - .checked_mul(*count) + .checked_mul(count) .expect("Multiplication overflow") .try_into() .expect("Overflow while converting to i64"),