From 04314fd91c70da0b3e418767246657f91480f6b1 Mon Sep 17 00:00:00 2001 From: Esteve Soler Arderiu Date: Thu, 28 Nov 2024 00:23:21 +0100 Subject: [PATCH 01/27] Implement profiler for `x86_64`. --- Cargo.toml | 1 + programs/examples/brainfuck.cairo | 11 +- src/bin/cairo-native-run.rs | 103 +++++++++++++++ src/compiler.rs | 64 +++++++--- src/context.rs | 6 + src/executor/jit.rs | 19 +++ src/libfuncs.rs | 49 ++++++-- src/libfuncs/array.rs | 92 +++++++------- src/libfuncs/bitwise.rs | 6 +- src/libfuncs/bool.rs | 9 +- src/libfuncs/bounded_int.rs | 22 ++-- src/libfuncs/box.rs | 6 +- src/libfuncs/bytes31.rs | 12 +- src/libfuncs/cast.rs | 22 ++-- src/libfuncs/circuit.rs | 51 ++++---- src/libfuncs/const.rs | 6 +- src/libfuncs/coupon.rs | 8 +- src/libfuncs/debug.rs | 16 ++- src/libfuncs/drop.rs | 3 +- src/libfuncs/dup.rs | 4 +- src/libfuncs/ec.rs | 36 +++--- src/libfuncs/enum.rs | 15 +-- src/libfuncs/felt252.rs | 14 +-- src/libfuncs/felt252_dict.rs | 10 +- src/libfuncs/felt252_dict_entry.rs | 21 +++- src/libfuncs/function_call.rs | 4 +- src/libfuncs/gas.rs | 27 ++-- src/libfuncs/int_range.rs | 12 +- src/libfuncs/mem.rs | 6 +- src/libfuncs/nullable.rs | 7 +- src/libfuncs/pedersen.rs | 3 +- src/libfuncs/poseidon.rs | 4 +- src/libfuncs/sint128.rs | 43 +++---- src/libfuncs/sint16.rs | 46 +++---- src/libfuncs/sint32.rs | 48 +++---- src/libfuncs/sint64.rs | 46 +++---- src/libfuncs/sint8.rs | 46 +++---- src/libfuncs/starknet.rs | 117 +++++++++-------- src/libfuncs/starknet/secp256.rs | 60 ++++----- src/libfuncs/starknet/testing.rs | 4 +- src/libfuncs/struct.rs | 8 +- src/libfuncs/uint128.rs | 51 +++----- src/libfuncs/uint16.rs | 46 +++---- src/libfuncs/uint256.rs | 22 ++-- src/libfuncs/uint32.rs | 45 +++---- src/libfuncs/uint512.rs | 6 +- src/libfuncs/uint64.rs | 35 ++---- src/libfuncs/uint8.rs | 45 +++---- src/metadata.rs | 1 + src/metadata/gas.rs | 6 +- src/metadata/profiler.rs | 193 +++++++++++++++++++++++++++++ 51 files changed, 882 insertions(+), 655 deletions(-) create mode 100644 src/metadata/profiler.rs diff --git a/Cargo.toml b/Cargo.toml index 7408f8848..10e470bd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ scarb = ["build-cli", "dep:scarb-ui", "dep:scarb-metadata"] with-cheatcode = [] with-debug-utils = [] with-mem-tracing = [] +with-profiler = [] with-runtime = ["dep:cairo-native-runtime"] # the aquamarine dep is only used in docs and cannot be detected as used by cargo udeps diff --git a/programs/examples/brainfuck.cairo b/programs/examples/brainfuck.cairo index d015de00d..e842f9e88 100644 --- a/programs/examples/brainfuck.cairo +++ b/programs/examples/brainfuck.cairo @@ -1,7 +1,8 @@ +use core::num::traits::WrappingSub; +use core::num::traits::WrappingAdd; use core::{ - traits::Default, - array::{ArrayTrait, SpanTrait}, debug::PrintTrait, dict::Felt252DictTrait, - integer::{u8_wrapping_add, u8_wrapping_sub}, option::OptionTrait, traits::Into, + traits::Default, array::{ArrayTrait, SpanTrait}, debug::PrintTrait, dict::Felt252DictTrait, + option::OptionTrait, traits::Into, }; fn generate_jump_table(program: @Array) -> Felt252Dict { @@ -50,9 +51,9 @@ fn run_program(program: @Array, input: Option>) { } else if op_code == '<' { mp -= 1; } else if op_code == '+' { - memory.insert(mp, u8_wrapping_add(memory.get(mp), 1)); + memory.insert(mp, memory.get(mp).wrapping_add(1)); } else if op_code == '-' { - memory.insert(mp, u8_wrapping_sub(memory.get(mp), 1)); + memory.insert(mp, memory.get(mp).wrapping_sub(1)); } else if op_code == '.' { memory.get(mp).print(); } else if op_code == ',' { diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index 32fd46b95..1d1a38a8c 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -44,6 +44,10 @@ struct Args { /// Optimization level, Valid: 0, 1, 2, 3. Values higher than 3 are considered as 3. #[arg(short = 'O', long, default_value_t = 0)] opt_level: u8, + + #[cfg(feature = "with-profiler")] + #[arg(long)] + profiler_output: Option, } fn main() -> anyhow::Result<()> { @@ -138,5 +142,104 @@ fn main() -> anyhow::Result<()> { println!("Remaining gas: {gas}"); } + #[cfg(feature = "with-profiler")] + if let Some(profiler_output) = args.profiler_output { + use cairo_lang_sierra::{ids::ConcreteLibfuncId, program::Statement}; + use std::{collections::HashMap, fs::File, io::Write}; + + let mut trace = HashMap::, u64)>::new(); + + for (statement_idx, tick_delta) in cairo_native::metadata::profiler::ProfilerImpl::take() { + if let Statement::Invocation(invocation) = &sierra_program.statements[statement_idx.0] { + let (tick_deltas, extra_count) = + trace.entry(invocation.libfunc_id.clone()).or_default(); + + if tick_delta != u64::MAX { + tick_deltas.push(tick_delta); + } else { + *extra_count += 1; + } + } + } + + let mut trace = trace + .into_iter() + .map(|(libfunc_id, (mut tick_deltas, extra_count))| { + tick_deltas.sort(); + + // Drop outliers. + { + let q1 = tick_deltas[tick_deltas.len() / 4]; + let q3 = tick_deltas[3 * tick_deltas.len() / 4]; + let iqr = q3 - q1; + + let q1_thr = q1.saturating_sub(iqr + iqr / 2); + let q3_thr = q3 + (iqr + iqr / 2); + + tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); + } + + // Compute the quartiles. + let quartiles = [ + *tick_deltas.first().unwrap(), + tick_deltas[tick_deltas.len() / 4], + tick_deltas[tick_deltas.len() / 2], + tick_deltas[3 * tick_deltas.len() / 4], + *tick_deltas.last().unwrap(), + ]; + + // Compuite the average. + let average = + tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; + + // Compute the standard deviation. + let std_dev = { + let sum = tick_deltas + .iter() + .copied() + .map(|x| x as f64) + .map(|x| (x - average)) + .map(|x| x * x) + .sum::(); + sum / (tick_deltas.len() as u64 + extra_count) as f64 + }; + + ( + libfunc_id, + ( + tick_deltas.len() as u64 + extra_count, + tick_deltas.iter().sum::() + + (extra_count as f64 * average).round() as u64, + quartiles, + average, + std_dev, + ), + ) + }) + .collect::>(); + + // Sort libfuncs by the order in which they are declared. + trace.sort_by_key(|(libfunc_id, _)| { + sierra_program + .libfunc_declarations + .iter() + .enumerate() + .find_map(|(i, x)| (&x.id == libfunc_id).then_some(i)) + .unwrap() + }); + + let mut output = File::create(profiler_output)?; + + for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in trace { + writeln!(output, "{libfunc_id}")?; + writeln!(output, " Samples : {n_samples}")?; + writeln!(output, " Sum : {sum}")?; + writeln!(output, " Average : {average}")?; + writeln!(output, " Deviation: {std_dev}")?; + writeln!(output, " Quartiles: {quartiles:?}")?; + writeln!(output)?; + } + } + Ok(()) } diff --git a/src/compiler.rs b/src/compiler.rs index d7c35f235..32073ca08 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -524,26 +524,6 @@ fn compile_func( let (state, _) = edit_state::take_args(state, invocation.args.iter())?; - let helper = LibfuncHelper { - module, - init_block: &pre_entry_block, - region: ®ion, - blocks_arena: &blocks_arena, - last_block: Cell::new(block), - branches: generate_branching_targets( - &blocks, - statements, - statement_idx, - invocation, - &state, - ), - results: invocation - .branches - .iter() - .map(|x| vec![Cell::new(None); x.results.len()]) - .collect::>(), - }; - let libfunc = registry.get_libfunc(&invocation.libfunc_id)?; if is_recursive { if let Some(target) = libfunc.is_function_call() { @@ -594,6 +574,45 @@ fn compile_func( } } + #[allow(unused_mut)] + let mut helper = LibfuncHelper { + module, + init_block: &pre_entry_block, + region: ®ion, + blocks_arena: &blocks_arena, + last_block: Cell::new(block), + branches: generate_branching_targets( + &blocks, + statements, + statement_idx, + invocation, + &state, + ), + results: invocation + .branches + .iter() + .map(|x| vec![Cell::new(None); x.results.len()]) + .collect::>(), + + #[cfg(feature = "with-profiler")] + profiler: match libfunc { + CoreConcreteLibfunc::FunctionCall(_) => { + // Tail-recursive function calls are broken. Also it'd include the entire function which + // doesn't make sense, therefore it's ignored on purpose. + None + } + _ => match metadata.remove::() + { + Some(profiler_meta) => { + let t0 = profiler_meta + .measure_timestamp(context, block, location)?; + Some((profiler_meta, statement_idx, t0)) + } + None => None, + }, + }, + }; + libfunc.build( context, registry, @@ -604,6 +623,11 @@ fn compile_func( )?; assert!(block.terminator().is_some()); + #[cfg(feature = "with-profiler")] + if let Some((profiler_meta, _, _)) = helper.profiler.take() { + metadata.insert(profiler_meta); + } + if let Some(tailrec_meta) = metadata.remove::() { if let Some(return_block) = tailrec_meta.return_target() { tailrec_state = Some((tailrec_meta.depth_counter(), return_block)); diff --git a/src/context.rs b/src/context.rs index de15fb9f2..ab3487362 100644 --- a/src/context.rs +++ b/src/context.rs @@ -167,6 +167,12 @@ impl NativeContext { // already some metadata of the same type. metadata.insert(gas_metadata); + #[cfg(feature = "with-profiler")] + metadata.insert(crate::metadata::profiler::ProfilerMeta::new( + &self.context, + &module, + )?); + // Create the Sierra program registry let registry = ProgramRegistry::::new(program)?; diff --git a/src/executor/jit.rs b/src/executor/jit.rs index 500cfcdf0..9a0872803 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -85,6 +85,9 @@ impl<'m> JitNativeExecutor<'m> { let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; + #[cfg(feature = "with-profiler")] + self.setup_profiling(); + super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -112,6 +115,9 @@ impl<'m> JitNativeExecutor<'m> { let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; + #[cfg(feature = "with-profiler")] + self.setup_profiling(); + super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -138,6 +144,9 @@ impl<'m> JitNativeExecutor<'m> { let set_builtin_costs_fnptr: extern "C" fn(*const u64) -> *const u64 = unsafe { std::mem::transmute(self.engine.lookup("cairo_native__set_costs_builtin")) }; + #[cfg(feature = "with-profiler")] + self.setup_profiling(); + ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -178,4 +187,14 @@ impl<'m> JitNativeExecutor<'m> { .get_function(function_id) .map(|func| &func.signature)?) } + + #[cfg(feature = "with-profiler")] + fn setup_profiling(&self) { + unsafe { + let callback_ptr: *mut extern "C" fn(u64, u64) = + self.engine.lookup("__profiler_callback").cast(); + + *callback_ptr = crate::metadata::profiler::ProfilerImpl::callback; + } + } } diff --git a/src/libfuncs.rs b/src/libfuncs.rs index 126d53fec..c61abbef5 100644 --- a/src/libfuncs.rs +++ b/src/libfuncs.rs @@ -21,7 +21,7 @@ use cairo_lang_sierra::{ }; use melior::{ dialect::{arith, cf}, - ir::{Block, BlockRef, Location, Module, Operation, Region, Value}, + ir::{Block, BlockRef, Location, Module, Region, Value}, Context, }; use num_bigint::BigInt; @@ -277,6 +277,13 @@ where pub branches: Vec<(&'this Block<'ctx>, Vec>)>, pub results: Vec>>>>, + + #[cfg(feature = "with-profiler")] + pub profiler: Option<( + crate::metadata::profiler::ProfilerMeta, + cairo_lang_sierra::program::StatementIdx, + (Value<'ctx, 'this>, Value<'ctx, 'this>), + )>, } impl<'ctx, 'this> LibfuncHelper<'ctx, 'this> @@ -328,10 +335,11 @@ where /// used later on when required. fn br( &self, + block: &'this Block<'ctx>, branch: usize, results: &[Value<'ctx, 'this>], location: Location<'ctx>, - ) -> Operation<'ctx> { + ) -> Result<()> { let (successor, operands) = &self.branches[branch]; for (dst, src) in self.results[branch].iter().zip(results) { @@ -347,7 +355,11 @@ where }) .collect::>(); - cf::br(successor, &destination_operands, location) + #[cfg(feature = "with-profiler")] + self.push_profiler_frame(unsafe { self.context().to_ref() }, block, location)?; + + block.append_operation(cf::br(successor, &destination_operands, location)); + Ok(()) } /// Creates a conditional binary branching operation, potentially jumping out of the libfunc and @@ -362,11 +374,12 @@ where fn cond_br( &self, context: &'ctx Context, + block: &'this Block<'ctx>, condition: Value<'ctx, 'this>, branches: [usize; 2], results: [&[Value<'ctx, 'this>]; 2], location: Location<'ctx>, - ) -> Operation<'ctx> { + ) -> Result<()> { let (block_true, args_true) = { let (successor, operands) = &self.branches[branches[0]]; @@ -405,7 +418,10 @@ where (*successor, destination_operands) }; - cf::cond_br( + #[cfg(feature = "with-profiler")] + self.push_profiler_frame(context, block, location)?; + + block.append_operation(cf::cond_br( context, condition, block_true, @@ -413,7 +429,25 @@ where &args_true, &args_false, location, - ) + )); + Ok(()) + } + + #[cfg(feature = "with-profiler")] + fn push_profiler_frame( + &self, + context: &'ctx Context, + block: &'this Block<'ctx>, + location: Location<'ctx>, + ) -> Result<()> { + if let Some((profiler_meta, statement_idx, t0)) = self.profiler.as_ref() { + let t0 = *t0; + let t1 = profiler_meta.measure_timestamp(context, block, location)?; + + profiler_meta.push_frame(context, block, statement_idx.0, t0, t1, location)?; + } + + Ok(()) } } @@ -486,6 +520,5 @@ fn build_noop<'ctx, 'this, const N: usize, const PROCESS_BUILTINS: bool>( params.push(param_val); } - entry.append_operation(helper.br(0, ¶ms, location)); - Ok(()) + helper.br(entry, 0, ¶ms, location) } diff --git a/src/libfuncs/array.rs b/src/libfuncs/array.rs index 7cf2ac77a..7f663cd90 100644 --- a/src/libfuncs/array.rs +++ b/src/libfuncs/array.rs @@ -118,8 +118,7 @@ pub fn build_new<'ctx, 'this>( let value = entry.insert_value(context, location, value, k0, 2)?; let value = entry.insert_value(context, location, value, k0, 3)?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `array_append` libfunc. @@ -310,7 +309,7 @@ pub fn build_append<'ctx, 'this>( let value = append_block.insert_value(context, location, append_block.arg(0)?, array_len, 2)?; - append_block.append_operation(helper.br(0, &[value], location)); + helper.br(append_block, 0, &[value], location)?; } Ok(()) @@ -357,8 +356,7 @@ pub fn build_len<'ctx, 'this>( _ => {} } - entry.append_operation(helper.br(0, &[array_len], location)); - Ok(()) + helper.br(entry, 0, &[array_len], location) } /// Generate MLIR operations for the `array_get` libfunc. @@ -528,20 +526,22 @@ pub fn build_get<'ctx, 'this>( } valid_block.append_operation(ReallocBindingsMeta::free(context, ptr, location)?); - valid_block.append_operation(helper.br(0, &[range_check, target_ptr], location)); + helper.br(valid_block, 0, &[range_check, target_ptr], location)?; } - metadata - .get::() - .ok_or(Error::MissingMetadata)? - .invoke_override( - context, - error_block, - location, - &info.param_signatures()[1].ty, - value, - )?; - error_block.append_operation(helper.br(1, &[range_check], location)); + { + metadata + .get::() + .ok_or(Error::MissingMetadata)? + .invoke_override( + context, + error_block, + location, + &info.param_signatures()[1].ty, + value, + )?; + helper.br(error_block, 1, &[range_check], location)?; + } Ok(()) } @@ -629,10 +629,11 @@ pub fn build_pop_front<'ctx, 'this>( let new_start = valid_block.addi(array_start, k1, location)?; let value = valid_block.insert_value(context, location, value, new_start, 1)?; - valid_block.append_operation(helper.br(0, &[value, target_ptr], location)); + helper.br(valid_block, 0, &[value, target_ptr], location)?; } - empty_block.append_operation(helper.br(1, &[value], location)); + helper.br(empty_block, 1, &[value], location)?; + Ok(()) } @@ -719,20 +720,22 @@ pub fn build_pop_front_consume<'ctx, 'this>( let new_start = valid_block.addi(array_start, k1, location)?; let value = valid_block.insert_value(context, location, value, new_start, 1)?; - valid_block.append_operation(helper.br(0, &[value, target_ptr], location)); + helper.br(valid_block, 0, &[value, target_ptr], location)?; } - metadata - .get::() - .ok_or(Error::MissingMetadata)? - .invoke_override( - context, - empty_block, - location, - &info.param_signatures()[0].ty, - value, - )?; - empty_block.append_operation(helper.br(1, &[], location)); + { + metadata + .get::() + .ok_or(Error::MissingMetadata)? + .invoke_override( + context, + empty_block, + location, + &info.param_signatures()[0].ty, + value, + )?; + helper.br(empty_block, 1, &[], location)?; + } Ok(()) } @@ -833,10 +836,11 @@ pub fn build_snapshot_pop_back<'ctx, 'this>( let value = valid_block.insert_value(context, location, value, new_end, 2)?; - valid_block.append_operation(helper.br(0, &[value, target_ptr], location)); + helper.br(valid_block, 0, &[value, target_ptr], location)?; } - empty_block.append_operation(helper.br(1, &[value], location)); + helper.br(empty_block, 1, &[value], location)?; + Ok(()) } @@ -954,10 +958,10 @@ pub fn build_snapshot_multi_pop_front<'ctx, 'this>( valid_block.insert_value(context, location, array, new_array_start, 1)? }; - valid_block.append_operation(helper.br(0, &[range_check, array, return_ptr], location)); + helper.br(valid_block, 0, &[range_check, array, return_ptr], location)?; } - invalid_block.append_operation(helper.br(1, &[range_check, array], location)); + helper.br(invalid_block, 1, &[range_check, array], location)?; Ok(()) } @@ -1080,10 +1084,10 @@ pub fn build_snapshot_multi_pop_back<'ctx, 'this>( valid_block.insert_value(context, location, array, new_array_end, 2)? }; - valid_block.append_operation(helper.br(0, &[range_check, array, return_ptr], location)); + helper.br(valid_block, 0, &[range_check, array, return_ptr], location)?; } - invalid_block.append_operation(helper.br(1, &[range_check, array], location)); + helper.br(invalid_block, 1, &[range_check, array], location)?; Ok(()) } @@ -1206,7 +1210,7 @@ pub fn build_slice<'ctx, 'this>( _ => {} }; - slice_block.append_operation(helper.br(0, &[range_check, value], location)); + helper.br(slice_block, 0, &[range_check, value], location)?; } { @@ -1231,7 +1235,7 @@ pub fn build_slice<'ctx, 'this>( entry.arg(1)?, )?; - error_block.append_operation(helper.br(1, &[range_check], location)); + helper.br(error_block, 1, &[range_check], location)?; } Ok(()) @@ -1317,9 +1321,7 @@ pub fn build_span_from_tuple<'ctx, 'this>( let array_container = entry.insert_value(context, location, array_container, ptr, 0)?; - entry.append_operation(helper.br(0, &[array_container], location)); - - Ok(()) + helper.br(entry, 0, &[array_container], location) } fn assert_nonnull<'ctx, 'this>( @@ -1508,10 +1510,10 @@ pub fn build_tuple_from_span<'ctx, 'this>( ); block_clone.append_operation(ReallocBindingsMeta::free(context, array_ptr, location)?); - block_clone.append_operation(helper.br(0, &[box_ptr], location)); + helper.br(block_clone, 0, &[box_ptr], location)?; } - block_forward.append_operation(helper.br(0, &[array_ptr], location)); + helper.br(block_forward, 0, &[array_ptr], location)?; } { @@ -1536,7 +1538,7 @@ pub fn build_tuple_from_span<'ctx, 'this>( entry.arg(0)?, )?; - block_err.append_operation(helper.br(1, &[], location)); + helper.br(block_err, 1, &[], location)?; } Ok(()) diff --git a/src/libfuncs/bitwise.rs b/src/libfuncs/bitwise.rs index 294640853..4e0dc7ef7 100644 --- a/src/libfuncs/bitwise.rs +++ b/src/libfuncs/bitwise.rs @@ -34,12 +34,12 @@ pub fn build<'ctx, 'this>( let logical_xor = entry.append_op_result(arith::xori(lhs, rhs, location))?; let logical_or = entry.append_op_result(arith::ori(lhs, rhs, location))?; - entry.append_operation(helper.br( + helper.br( + entry, 0, &[bitwise, logical_and, logical_xor, logical_or], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/bool.rs b/src/libfuncs/bool.rs index da431ad75..913fd22ba 100644 --- a/src/libfuncs/bool.rs +++ b/src/libfuncs/bool.rs @@ -126,8 +126,7 @@ fn build_bool_binary<'ctx, 'this>( let res = entry.insert_value(context, location, res, new_tag_value, 0)?; - entry.append_operation(helper.br(0, &[res], location)); - Ok(()) + helper.br(entry, 0, &[res], location) } /// Generate MLIR operations for the `bool_not_impl` libfunc. @@ -168,8 +167,7 @@ pub fn build_bool_not<'ctx, 'this>( ))?; let res = entry.insert_value(context, location, res, new_tag_value, 0)?; - entry.append_operation(helper.br(0, &[res], location)); - Ok(()) + helper.br(entry, 0, &[res], location) } /// Generate MLIR operations for the `unbox` libfunc. @@ -204,8 +202,7 @@ pub fn build_bool_to_felt252<'ctx, 'this>( let result = entry.extui(tag_value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } #[cfg(test)] diff --git a/src/libfuncs/bounded_int.rs b/src/libfuncs/bounded_int.rs index 5da4785e0..0b99cbf4f 100644 --- a/src/libfuncs/bounded_int.rs +++ b/src/libfuncs/bounded_int.rs @@ -190,8 +190,7 @@ fn build_add<'ctx, 'this>( res_value }; - entry.append_operation(helper.br(0, &[res_value], location)); - Ok(()) + helper.br(entry, 0, &[res_value], location) } /// Generate MLIR operations for the `bounded_int_sub` libfunc. @@ -318,8 +317,7 @@ fn build_sub<'ctx, 'this>( res_value }; - entry.append_operation(helper.br(0, &[res_value], location)); - Ok(()) + helper.br(entry, 0, &[res_value], location) } /// Generate MLIR operations for the `bounded_int_mul` libfunc. @@ -438,8 +436,7 @@ fn build_mul<'ctx, 'this>( res_value }; - entry.append_operation(helper.br(0, &[res_value], location)); - Ok(()) + helper.br(entry, 0, &[res_value], location) } /// Generate MLIR operations for the `bounded_int_divrem` libfunc. @@ -583,8 +580,7 @@ fn build_divrem<'ctx, 'this>( rem_value }; - entry.append_operation(helper.br(0, &[range_check, div_value, rem_value], location)); - Ok(()) + helper.br(entry, 0, &[range_check, div_value, rem_value], location) } /// Generate MLIR operations for the `bounded_int_constrain` libfunc. @@ -666,7 +662,7 @@ fn build_constrain<'ctx, 'this>( res_value }; - lower_block.append_operation(helper.br(0, &[range_check, res_value], location)); + helper.br(lower_block, 0, &[range_check, res_value], location)?; } { @@ -693,7 +689,7 @@ fn build_constrain<'ctx, 'this>( res_value }; - upper_block.append_operation(helper.br(1, &[range_check, res_value], location)); + helper.br(upper_block, 1, &[range_check, res_value], location)?; } Ok(()) @@ -722,14 +718,14 @@ fn build_is_zero<'ctx, 'this>( let k0 = entry.const_int_from_type(context, location, 0, src_value.r#type())?; let src_is_zero = entry.cmpi(context, CmpiPredicate::Eq, src_value, k0, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, src_is_zero, [0, 1], [&[], &[src_value]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `bounded_int_wrap_non_zero` libfunc. diff --git a/src/libfuncs/box.rs b/src/libfuncs/box.rs index 224340959..3e48517ca 100644 --- a/src/libfuncs/box.rs +++ b/src/libfuncs/box.rs @@ -107,8 +107,7 @@ pub fn build_into_box<'ctx, 'this>( ))), )); - entry.append_operation(helper.br(0, &[ptr], location)); - Ok(()) + helper.br(entry, 0, &[ptr], location) } /// Generate MLIR operations for the `unbox` libfunc. @@ -146,8 +145,7 @@ pub fn build_unbox<'ctx, 'this>( entry.append_operation(ReallocBindingsMeta::free(context, entry.arg(0)?, location)?); - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } #[cfg(test)] diff --git a/src/libfuncs/bytes31.rs b/src/libfuncs/bytes31.rs index 63e59450a..e3cc647b5 100644 --- a/src/libfuncs/bytes31.rs +++ b/src/libfuncs/bytes31.rs @@ -75,9 +75,7 @@ pub fn build_const<'ctx, 'this>( location, )); - entry.append_operation(helper.br(0, &[op0.result(0)?.into()], location)); - - Ok(()) + helper.br(entry, 0, &[op0.result(0)?.into()], location) } /// Generate MLIR operations for the `bytes31_to_felt252` libfunc. @@ -101,9 +99,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u8_from_felt252` libfunc. @@ -161,9 +157,9 @@ pub fn build_from_felt252<'ctx, 'this>( )); let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); + helper.br(block_success, 0, &[range_check, value], location)?; - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/libfuncs/cast.rs b/src/libfuncs/cast.rs index 1e8ede5fd..7627c8306 100644 --- a/src/libfuncs/cast.rs +++ b/src/libfuncs/cast.rs @@ -60,14 +60,14 @@ pub fn build_downcast<'ctx, 'this>( if info.signature.param_signatures[1].ty == info.signature.branch_signatures[0].vars[1].ty { let k0 = entry.const_int(context, location, 0, 1)?; - entry.append_operation(helper.cond_br( + return helper.cond_br( context, + entry, k0, [0, 1], [&[range_check, src_value], &[range_check]], location, - )); - return Ok(()); + ); } let src_ty = registry.get_type(&info.signature.param_signatures[1].ty)?; @@ -183,13 +183,14 @@ pub fn build_downcast<'ctx, 'this>( let is_in_bounds = entry.const_int(context, location, 1, 1)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_bounds, [0, 1], [&[range_check, dst_value], &[range_check]], location, - )); + )?; } else { let lower_check = if dst_range.lower > src_range.lower { let dst_lower = entry.const_int_from_type( @@ -267,13 +268,14 @@ pub fn build_downcast<'ctx, 'this>( } else { dst_value }; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_bounds, [0, 1], [&[range_check, dst_value], &[range_check]], location, - )); + )?; } Ok(()) @@ -292,8 +294,7 @@ pub fn build_upcast<'ctx, 'this>( let src_value = entry.arg(0)?; if info.signature.param_signatures[0].ty == info.signature.branch_signatures[0].vars[0].ty { - entry.append_operation(helper.br(0, &[src_value], location)); - return Ok(()); + return helper.br(entry, 0, &[src_value], location); } let src_ty = registry.get_type(&info.signature.param_signatures[0].ty)?; @@ -383,8 +384,7 @@ pub fn build_upcast<'ctx, 'this>( dst_value }; - entry.append_operation(helper.br(0, &[dst_value], location)); - Ok(()) + helper.br(entry, 0, &[dst_value], location) } #[cfg(test)] diff --git a/src/libfuncs/circuit.rs b/src/libfuncs/circuit.rs index b7f0ad443..448a27f5d 100644 --- a/src/libfuncs/circuit.rs +++ b/src/libfuncs/circuit.rs @@ -123,9 +123,7 @@ fn build_init_circuit_data<'ctx, 'this>( &[k0], )?; - entry.append_operation(helper.br(0, &[rc, accumulator], location)); - - Ok(()) + helper.br(entry, 0, &[rc, accumulator], location) } /// Generate MLIR operations for the `add_circuit_input` libfunc. @@ -223,7 +221,7 @@ fn build_add_input<'ctx, 'this>( let accumulator = middle_insert_block.load(context, location, accumulator_ptr, accumulator.r#type())?; - middle_insert_block.append_operation(helper.br(1, &[accumulator], location)); + helper.br(middle_insert_block, 1, &[accumulator], location)?; } // If is last insert, then: @@ -297,7 +295,7 @@ fn build_add_input<'ctx, 'this>( // Load data from pointer let data = last_insert_block.load(context, location, data_ptr, data_type)?; - last_insert_block.append_operation(helper.br(0, &[data], location)); + helper.br(last_insert_block, 0, &[data], location)?; } Ok(()) @@ -319,9 +317,14 @@ fn build_try_into_circuit_modulus<'ctx, 'this>( let is_valid = entry.cmpi(context, arith::CmpiPredicate::Ugt, modulus, k1, location)?; - entry.append_operation(helper.cond_br(context, is_valid, [0, 1], [&[modulus], &[]], location)); - - Ok(()) + helper.cond_br( + context, + entry, + is_valid, + [0, 1], + [&[modulus], &[]], + location, + ) } /// Generate MLIR operations for the `get_circuit_descriptor` libfunc. @@ -342,9 +345,7 @@ fn build_get_descriptor<'ctx, 'this>( let unit = entry.append_op_result(llvm::undef(descriptor_type, location))?; - entry.append_operation(helper.br(0, &[unit], location)); - - Ok(()) + helper.br(entry, 0, &[unit], location) } /// Generate MLIR operations for the `eval_circuit` libfunc. @@ -413,7 +414,7 @@ fn build_eval<'ctx, 'this>( &gates, )?; - ok_block.append_operation(helper.br(0, &[add_mod, mul_mod, outputs], location)); + helper.br(ok_block, 0, &[add_mod, mul_mod, outputs], location)?; } // Error case @@ -438,7 +439,12 @@ fn build_eval<'ctx, 'this>( registry.build_type(context, helper, registry, metadata, failure_type_id)?, location, ))?; - err_block.append_operation(helper.br(1, &[add_mod, mul_mod, partial, failure], location)); + helper.br( + err_block, + 1, + &[add_mod, mul_mod, partial, failure], + location, + )?; } Ok(()) @@ -711,9 +717,7 @@ fn build_failure_guarantee_verify<'ctx, 'this>( let guarantee = entry.append_op_result(llvm::undef(guarantee_type, location))?; - entry.append_operation(helper.br(0, &[rc, mul_mod, guarantee], location)); - - Ok(()) + helper.br(entry, 0, &[rc, mul_mod, guarantee], location) } /// Generate MLIR operations for the `u96_limbs_less_than_guarantee_verify` libfunc. @@ -740,15 +744,14 @@ fn build_u96_limbs_less_than_guarantee_verify<'ctx, 'this>( let u96 = entry.append_op_result(llvm::undef(u96_type, location))?; let kfalse = entry.const_int(context, location, 0, 64)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, kfalse, [0, 1], [&[guarantee], &[u96]], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `u96_single_limb_less_than_guarantee_verify` libfunc. @@ -767,9 +770,7 @@ fn build_u96_single_limb_less_than_guarantee_verify<'ctx, 'this>( let u96_type = registry.build_type(context, helper, registry, metadata, u96_type_id)?; let u96 = entry.append_op_result(llvm::undef(u96_type, location))?; - entry.append_operation(helper.br(0, &[u96], location)); - - Ok(()) + helper.br(entry, 0, &[u96], location) } /// Generate MLIR operations for the `get_circuit_output` libfunc. @@ -811,9 +812,7 @@ fn build_get_output<'ctx, 'this>( registry.build_type(context, helper, registry, metadata, guarantee_type_id)?; let guarantee = entry.append_op_result(llvm::undef(guarantee_type, location))?; - entry.append_operation(helper.br(0, &[output_struct, guarantee], location)); - - Ok(()) + helper.br(entry, 0, &[output_struct, guarantee], location) } fn u384_struct_to_integer<'a>( diff --git a/src/libfuncs/const.rs b/src/libfuncs/const.rs index 85ebdc51c..8553cb57d 100644 --- a/src/libfuncs/const.rs +++ b/src/libfuncs/const.rs @@ -88,8 +88,7 @@ pub fn build_const_as_box<'ctx, 'this>( // Store constant in box entry.store(context, location, ptr, value)?; - entry.append_operation(helper.br(0, &[ptr], location)); - Ok(()) + helper.br(entry, 0, &[ptr], location) } /// Generate MLIR operations for the `const_as_immediate` libfunc. @@ -113,8 +112,7 @@ pub fn build_const_as_immediate<'ctx, 'this>( context, registry, entry, location, helper, metadata, const_type, )?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } pub fn build_const_type_value<'ctx, 'this>( diff --git a/src/libfuncs/coupon.rs b/src/libfuncs/coupon.rs index f47999fbd..69c07bd08 100644 --- a/src/libfuncs/coupon.rs +++ b/src/libfuncs/coupon.rs @@ -73,9 +73,7 @@ pub fn build_buy<'ctx, 'this>( )?; let coupon = entry.append_op_result(llvm::undef(ty, location))?; - entry.append_operation(helper.br(0, &[coupon], location)); - - Ok(()) + helper.br(entry, 0, &[coupon], location) } /// Generate MLIR operations for the `coupon` libfunc. @@ -92,7 +90,5 @@ pub fn build_refund<'ctx, 'this>( // let gas = metadata.get::().ok_or(Error::MissingMetadata)?; // let gas_cost = gas.initial_required_gas(&info.function.id); - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) + helper.br(entry, 0, &[], location) } diff --git a/src/libfuncs/debug.rs b/src/libfuncs/debug.rs index 770db996a..d1f5ed129 100644 --- a/src/libfuncs/debug.rs +++ b/src/libfuncs/debug.rs @@ -31,12 +31,12 @@ use melior::{ Context, }; -pub fn build<'ctx>( +pub fn build<'ctx, 'this>( context: &'ctx Context, registry: &ProgramRegistry, - entry: &Block<'ctx>, + entry: &'this Block<'ctx>, location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, '_>, + helper: &LibfuncHelper<'ctx, 'this>, metadata: &mut MetadataStorage, selector: &DebugConcreteLibfunc, ) -> Result<()> { @@ -47,12 +47,12 @@ pub fn build<'ctx>( } } -pub fn build_print<'ctx>( +pub fn build_print<'ctx, 'this>( context: &'ctx Context, registry: &ProgramRegistry, - entry: &Block<'ctx>, + entry: &'this Block<'ctx>, location: Location<'ctx>, - helper: &LibfuncHelper<'ctx, '_>, + helper: &LibfuncHelper<'ctx, 'this>, metadata: &mut MetadataStorage, info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { @@ -121,7 +121,5 @@ pub fn build_print<'ctx>( location, ); - entry.append_operation(helper.br(0, &[], location)); - - Ok(()) + helper.br(entry, 0, &[], location) } diff --git a/src/libfuncs/drop.rs b/src/libfuncs/drop.rs index eec53cfce..a133978f4 100644 --- a/src/libfuncs/drop.rs +++ b/src/libfuncs/drop.rs @@ -51,6 +51,5 @@ pub fn build<'ctx, 'this>( )?; } - entry.append_operation(helper.br(0, &[], location)); - Ok(()) + helper.br(entry, 0, &[], location) } diff --git a/src/libfuncs/dup.rs b/src/libfuncs/dup.rs index a0f6112b4..620fedfde 100644 --- a/src/libfuncs/dup.rs +++ b/src/libfuncs/dup.rs @@ -45,7 +45,5 @@ pub fn build<'ctx, 'this>( &info.signature.param_signatures[0].ty, entry.arg(0)?, )?; - entry.append_operation(helper.br(0, &[values.0, values.1], location)); - - Ok(()) + helper.br(entry, 0, &[values.0, values.1], location) } diff --git a/src/libfuncs/ec.rs b/src/libfuncs/ec.rs index 12b8bdfae..12358aecd 100644 --- a/src/libfuncs/ec.rs +++ b/src/libfuncs/ec.rs @@ -91,14 +91,14 @@ pub fn build_is_zero<'ctx, 'this>( let k0 = entry.const_int(context, location, 0, 252)?; let y_is_zero = entry.cmpi(context, CmpiPredicate::Eq, y, k0, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, y_is_zero, [0, 1], [&[], &[entry.arg(0)?]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `ec_neg` libfunc. @@ -134,8 +134,7 @@ pub fn build_neg<'ctx, 'this>( let result = entry.insert_value(context, location, entry.arg(0)?, y_neg, 1)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `ec_point_from_x_nz` libfunc. @@ -179,14 +178,14 @@ pub fn build_point_from_x<'ctx, 'this>( let point = entry.load(context, location, point_ptr, ec_point_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result, [0, 1], [&[range_check, point], &[range_check]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `ec_state_add` libfunc. @@ -233,8 +232,7 @@ pub fn build_state_add<'ctx, 'this>( let state = entry.load(context, location, state_ptr, ec_state_ty)?; - entry.append_operation(helper.br(0, &[state], location)); - Ok(()) + helper.br(entry, 0, &[state], location) } /// Generate MLIR operations for the `ec_state_add_mul` libfunc. @@ -289,8 +287,7 @@ pub fn build_state_add_mul<'ctx, 'this>( let state = entry.load(context, location, state_ptr, ec_state_ty)?; - entry.append_operation(helper.br(0, &[ec_op, state], location)); - Ok(()) + helper.br(entry, 0, &[ec_op, state], location) } /// Generate MLIR operations for the `ec_state_try_finalize_nz` libfunc. @@ -335,8 +332,7 @@ pub fn build_state_finalize<'ctx, 'this>( let point = entry.load(context, location, point_ptr, ec_point_ty)?; - entry.append_operation(helper.cond_br(context, is_zero, [0, 1], [&[point], &[]], location)); - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[point], &[]], location) } /// Generate MLIR operations for the `ec_state_init` libfunc. @@ -374,8 +370,7 @@ pub fn build_state_init<'ctx, 'this>( let state = entry.load(context, location, state_ptr, ec_state_ty)?; - entry.append_operation(helper.br(0, &[state], location)); - Ok(()) + helper.br(entry, 0, &[state], location) } /// Generate MLIR operations for the `ec_point_try_new_nz` libfunc. @@ -417,8 +412,7 @@ pub fn build_try_new<'ctx, 'this>( .result(0)? .into(); - entry.append_operation(helper.cond_br(context, result, [0, 1], [&[point], &[]], location)); - Ok(()) + helper.cond_br(context, entry, result, [0, 1], [&[point], &[]], location) } /// Generate MLIR operations for the `ec_point_unwrap` libfunc. @@ -459,8 +453,7 @@ pub fn build_unwrap_point<'ctx, 'this>( 1, )?; - entry.append_operation(helper.br(0, &[x, y], location)); - Ok(()) + helper.br(entry, 0, &[x, y], location) } /// Generate MLIR operations for the `ec_point_zero` libfunc. @@ -489,8 +482,7 @@ pub fn build_zero<'ctx, 'this>( let point = entry.insert_value(context, location, point, k0, 1)?; - entry.append_operation(helper.br(0, &[point], location)); - Ok(()) + helper.br(entry, 0, &[point], location) } #[cfg(test)] diff --git a/src/libfuncs/enum.rs b/src/libfuncs/enum.rs index 1b2fba284..d5defdb3c 100644 --- a/src/libfuncs/enum.rs +++ b/src/libfuncs/enum.rs @@ -94,9 +94,8 @@ pub fn build_init<'ctx, 'this>( &info.signature.param_signatures[0].ty, info.index, )?; - entry.append_operation(helper.br(0, &[val], location)); - Ok(()) + helper.br(entry, 0, &[val], location) } #[allow(clippy::too_many_arguments)] @@ -246,9 +245,7 @@ pub fn build_from_bounded_int<'ctx, 'this>( let value = entry.append_op_result(llvm::undef(enum_ty, location))?; let value = entry.insert_value(context, location, value, tag_value, 0)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `enum_match` libfunc. @@ -283,7 +280,7 @@ pub fn build_match<'ctx, 'this>( entry.append_operation(llvm::unreachable(location)); } 1 => { - entry.append_operation(helper.br(0, &[entry.arg(0)?], location)); + helper.br(entry, 0, &[entry.arg(0)?], location)?; } _ => { let (layout, (tag_ty, _), variant_tys) = crate::types::r#enum::get_type_for_variants( @@ -400,7 +397,7 @@ pub fn build_match<'ctx, 'this>( } }; - block.append_operation(helper.br(i, &[payload_val], location)); + helper.br(block, i, &[payload_val], location)?; } } } @@ -444,7 +441,7 @@ pub fn build_snapshot_match<'ctx, 'this>( entry.append_operation(llvm::unreachable(location)); } 1 => { - entry.append_operation(helper.br(0, &[entry.arg(0)?], location)); + helper.br(entry, 0, &[entry.arg(0)?], location)?; } _ => { let (layout, (tag_ty, _), variant_tys) = crate::types::r#enum::get_type_for_variants( @@ -542,7 +539,7 @@ pub fn build_snapshot_match<'ctx, 'this>( } }; - block.append_operation(helper.br(i, &[payload_val], location)); + helper.br(block, i, &[payload_val], location)?; } } } diff --git a/src/libfuncs/felt252.rs b/src/libfuncs/felt252.rs index ad8225524..6be894e50 100644 --- a/src/libfuncs/felt252.rs +++ b/src/libfuncs/felt252.rs @@ -272,14 +272,11 @@ pub fn build_binary_operation<'ctx, 'this>( ))?; let result = inverse_result_block.trunci(result, felt252_ty, location)?; - inverse_result_block.append_operation(helper.br(0, &[result], location)); - return Ok(()); + return helper.br(inverse_result_block, 0, &[result], location); } }; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `felt252_const` libfunc. @@ -308,8 +305,8 @@ pub fn build_const<'ctx, 'this>( )?; let value = entry.const_int_from_type(context, location, value, felt252_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `felt252_is_zero` libfunc. @@ -327,8 +324,7 @@ pub fn build_is_zero<'ctx, 'this>( let k0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, k0, location)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - Ok(()) + helper.cond_br(context, entry, condition, [0, 1], [&[], &[arg0]], location) } #[cfg(test)] diff --git a/src/libfuncs/felt252_dict.rs b/src/libfuncs/felt252_dict.rs index 4b3f7a67d..4584c634a 100644 --- a/src/libfuncs/felt252_dict.rs +++ b/src/libfuncs/felt252_dict.rs @@ -56,8 +56,7 @@ pub fn build_new<'ctx, 'this>( let dict_ptr = runtime_bindings.dict_new(context, helper, entry, location)?; - entry.append_operation(helper.br(0, &[segment_arena, dict_ptr], location)); - Ok(()) + helper.br(entry, 0, &[segment_arena, dict_ptr], location) } pub fn build_squash<'ctx, 'this>( @@ -85,13 +84,12 @@ pub fn build_squash<'ctx, 'this>( let new_gas_builtin = entry.addi(gas_builtin, gas_refund, location)?; - entry.append_operation(helper.br( + helper.br( + entry, 0, &[range_check, new_gas_builtin, segment_arena, entry.arg(3)?], location, - )); - - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/felt252_dict_entry.rs b/src/libfuncs/felt252_dict_entry.rs index 50ac436e8..3047f027a 100644 --- a/src/libfuncs/felt252_dict_entry.rs +++ b/src/libfuncs/felt252_dict_entry.rs @@ -153,11 +153,18 @@ pub fn build_get<'ctx, 'this>( block_vacant.append_operation(cf::br(block_final, &[value], location)); } - let entry = block_final.append_op_result(llvm::undef(entry_ty, location))?; - let entry = - block_final.insert_values(context, location, entry, &[dict_ptr, entry_value_ptr_ptr])?; + { + let entry = block_final.append_op_result(llvm::undef(entry_ty, location))?; + let entry = block_final.insert_values( + context, + location, + entry, + &[dict_ptr, entry_value_ptr_ptr], + )?; + + helper.br(block_final, 0, &[entry, block_final.arg(0)?], location)?; + } - block_final.append_operation(helper.br(0, &[entry, block_final.arg(0)?], location)); Ok(()) } @@ -265,8 +272,10 @@ pub fn build_finalize<'ctx, 'this>( block_vacant.append_operation(cf::br(block_final, &[value_ptr], location)); } - block_final.store(context, location, block_final.arg(0)?, entry_value)?; - block_final.append_operation(helper.br(0, &[dict_ptr], location)); + { + block_final.store(context, location, block_final.arg(0)?, entry_value)?; + helper.br(block_final, 0, &[dict_ptr], location)?; + } Ok(()) } diff --git a/src/libfuncs/function_call.rs b/src/libfuncs/function_call.rs index 6bd322b91..22df0ebea 100644 --- a/src/libfuncs/function_call.rs +++ b/src/libfuncs/function_call.rs @@ -121,7 +121,7 @@ pub fn build<'ctx, 'this>( } } - cont_block.append_operation(helper.br(0, &results, location)); + helper.br(cont_block, 0, &results, location)?; } else { let mut result_types = Vec::new(); let return_types = info @@ -290,7 +290,7 @@ pub fn build<'ctx, 'this>( } } - entry.append_operation(helper.br(0, &results, location)); + helper.br(entry, 0, &results, location)?; } if let Some(tailrec_meta) = tailrec_meta { diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index db8a924f8..089bc43e9 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -58,11 +58,12 @@ pub fn build_get_available_gas<'ctx, 'this>( _metadata: &mut MetadataStorage, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let gas = entry.arg(0)?; - let gas_u128 = entry.extui(gas, IntegerType::new(context, 128).into(), location)?; + let i128_ty = IntegerType::new(context, 128).into(); + + let gas_u128 = entry.extui(entry.arg(0)?, i128_ty, location)?; + // The gas is returned as u128 on the second arg. - entry.append_operation(helper.br(0, &[entry.arg(0)?, gas_u128], location)); - Ok(()) + helper.br(entry, 0, &[entry.arg(0)?, gas_u128], location) } /// Generate MLIR operations for the `withdraw_gas` libfunc. @@ -142,15 +143,14 @@ pub fn build_withdraw_gas<'ctx, 'this>( ods::llvm::intr_usub_sat(context, current_gas, total_gas_cost_value, location).into(), )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_enough, [0, 1], [&[range_check, resulting_gas], &[range_check, current_gas]], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `withdraw_gas_all` libfunc. @@ -220,15 +220,14 @@ pub fn build_builtin_withdraw_gas<'ctx, 'this>( ods::llvm::intr_usub_sat(context, current_gas, total_gas_cost_value, location).into(), )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_enough, [0, 1], [&[range_check, resulting_gas], &[range_check, current_gas]], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `get_builtin_costs` libfunc. @@ -252,9 +251,7 @@ pub fn build_get_builtin_costs<'ctx, 'this>( .into() }; - entry.append_operation(helper.br(0, &[builtin_ptr], location)); - - Ok(()) + helper.br(entry, 0, &[builtin_ptr], location) } #[cfg(test)] diff --git a/src/libfuncs/int_range.rs b/src/libfuncs/int_range.rs index f231da6da..ad714bce2 100644 --- a/src/libfuncs/int_range.rs +++ b/src/libfuncs/int_range.rs @@ -83,14 +83,14 @@ pub fn build_int_range_try_new<'ctx, 'this>( let x_val = entry.append_op_result(arith::select(is_valid, x, y, location))?; let range = entry.insert_values(context, location, range, &[x_val, y])?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_valid, [0, 1], [&[range_check, range], &[range_check, range]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `int_range_pop_front` libfunc. @@ -130,14 +130,14 @@ pub fn build_int_range_pop_front<'ctx, 'this>( }; let range = entry.insert_value(context, location, range, x_p_1, 0)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_valid, [1, 0], // failure, success [&[range, x], &[]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/mem.rs b/src/libfuncs/mem.rs index 7f1a39485..37501f682 100644 --- a/src/libfuncs/mem.rs +++ b/src/libfuncs/mem.rs @@ -85,8 +85,7 @@ pub fn build_alloc_local<'ctx, 'this>( let value = entry.append_op_result(llvm::undef(target_type, location))?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `store_local` libfunc. @@ -99,6 +98,5 @@ pub fn build_store_local<'ctx, 'this>( _metadata: &mut MetadataStorage, _info: &SignatureAndTypeConcreteLibfunc, ) -> Result<()> { - entry.append_operation(helper.br(0, &[entry.arg(1)?], location)); - Ok(()) + helper.br(entry, 0, &[entry.arg(1)?], location) } diff --git a/src/libfuncs/nullable.rs b/src/libfuncs/nullable.rs index 79645e6cf..67f4787f4 100644 --- a/src/libfuncs/nullable.rs +++ b/src/libfuncs/nullable.rs @@ -65,8 +65,7 @@ fn build_null<'ctx, 'this>( let value = entry .append_op_result(ods::llvm::mlir_zero(context, pointer(context, 0), location).into())?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `match_nullable` libfunc. @@ -109,8 +108,8 @@ fn build_match_nullable<'ctx, 'this>( location, )); - block_is_null.append_operation(helper.br(0, &[], location)); - block_is_not_null.append_operation(helper.br(1, &[arg], location)); + helper.br(block_is_null, 0, &[], location)?; + helper.br(block_is_not_null, 1, &[arg], location)?; Ok(()) } diff --git a/src/libfuncs/pedersen.rs b/src/libfuncs/pedersen.rs index d9ee3d3f8..2bfcefa4d 100644 --- a/src/libfuncs/pedersen.rs +++ b/src/libfuncs/pedersen.rs @@ -96,8 +96,7 @@ pub fn build_pedersen<'ctx>( let result = entry.load(context, location, dst_ptr, i256_ty)?; let result = entry.trunci(result, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[pedersen_builtin, result], location)); - Ok(()) + helper.br(entry, 0, &[pedersen_builtin, result], location) } #[cfg(test)] diff --git a/src/libfuncs/poseidon.rs b/src/libfuncs/poseidon.rs index 3ad52694f..7afe71325 100644 --- a/src/libfuncs/poseidon.rs +++ b/src/libfuncs/poseidon.rs @@ -109,9 +109,7 @@ pub fn build_hades_permutation<'ctx>( let op1 = entry.trunci(op1_i256, felt252_ty, location)?; let op2 = entry.trunci(op2_i256, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[poseidon_builtin, op0, op1, op2], location)); - - Ok(()) + helper.br(entry, 0, &[poseidon_builtin, op0, op1, op2], location) } #[cfg(test)] diff --git a/src/libfuncs/sint128.rs b/src/libfuncs/sint128.rs index 0242913ed..f5ea53a51 100644 --- a/src/libfuncs/sint128.rs +++ b/src/libfuncs/sint128.rs @@ -82,9 +82,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i128 operation libfunc. @@ -152,15 +150,16 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between undeflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Oveflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; Ok(()) } @@ -185,15 +184,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i128_is_zero` libfunc. @@ -205,15 +203,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; - - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let value = entry.arg(0)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i128_to_felt252` libfunc. @@ -259,9 +254,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i128_from_felt252` libfunc. @@ -360,8 +353,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -386,14 +379,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/sint16.rs b/src/libfuncs/sint16.rs index c3b1e312d..db21bee9d 100644 --- a/src/libfuncs/sint16.rs +++ b/src/libfuncs/sint16.rs @@ -83,9 +83,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i16 operation libfunc. @@ -153,15 +151,16 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between underflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Overflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; Ok(()) } @@ -186,15 +185,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i16_is_zero` libfunc. @@ -206,15 +204,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i16_widemul` libfunc. @@ -242,8 +237,7 @@ pub fn build_widemul<'ctx, 'this>( let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `i16_to_felt252` libfunc. @@ -289,9 +283,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i16_from_felt252` libfunc. @@ -390,8 +382,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -416,14 +408,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/sint32.rs b/src/libfuncs/sint32.rs index 37d5251e6..3ad9f5d2b 100644 --- a/src/libfuncs/sint32.rs +++ b/src/libfuncs/sint32.rs @@ -83,9 +83,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i32 operation libfunc. @@ -153,15 +151,17 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between undeflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Oveflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; + Ok(()) } @@ -185,15 +185,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i32_is_zero` libfunc. @@ -205,15 +204,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i32_widemul` libfunc. @@ -241,8 +237,7 @@ pub fn build_widemul<'ctx, 'this>( let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `i32_to_felt252` libfunc. @@ -288,9 +283,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i32_from_felt252` libfunc. @@ -389,8 +382,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -415,15 +408,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/sint64.rs b/src/libfuncs/sint64.rs index e13366fe9..6f9de56da 100644 --- a/src/libfuncs/sint64.rs +++ b/src/libfuncs/sint64.rs @@ -83,9 +83,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i64 operation libfunc. @@ -153,15 +151,16 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between undeflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Oveflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; Ok(()) } @@ -186,15 +185,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i64_is_zero` libfunc. @@ -206,15 +204,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i64_widemul` libfunc. @@ -242,8 +237,7 @@ pub fn build_widemul<'ctx, 'this>( let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `i64_to_felt252` libfunc. @@ -289,9 +283,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i64_from_felt252` libfunc. @@ -390,8 +382,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -416,14 +408,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/sint8.rs b/src/libfuncs/sint8.rs index 0c19b6f35..7941e570f 100644 --- a/src/libfuncs/sint8.rs +++ b/src/libfuncs/sint8.rs @@ -83,9 +83,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the i8 operation libfunc. @@ -154,15 +152,16 @@ pub fn build_operation<'ctx, 'this>( location, )); // Check wether the result is positive to distinguish between underflowing & overflowing results - block_overflow.append_operation(helper.cond_br( + helper.cond_br( context, + block_overflow, is_positive, [1, 2], [&[range_check, op_result], &[range_check, op_result]], location, - )); + )?; // No Oveflow/Underflow -> In range result - block_not_overflow.append_operation(helper.br(0, &[range_check, op_result], location)); + helper.br(block_not_overflow, 0, &[range_check, op_result], location)?; Ok(()) } @@ -187,15 +186,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `i8_is_zero` libfunc. @@ -207,15 +205,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `i8_widemul` libfunc. @@ -243,8 +238,7 @@ pub fn build_widemul<'ctx, 'this>( let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `i8_to_felt252` libfunc. @@ -290,9 +284,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[final_result], location)); - - Ok(()) + helper.br(entry, 0, &[final_result], location) } /// Generate MLIR operations for the `i8_from_felt252` libfunc. @@ -392,8 +384,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } @@ -418,14 +410,14 @@ pub fn build_diff<'ctx, 'this>( let result = entry.append_op_result(arith::subi(lhs, rhs, location))?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_ge, [0, 1], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/starknet.rs b/src/libfuncs/starknet.rs index e0239ac45..f23d378d6 100644 --- a/src/libfuncs/starknet.rs +++ b/src/libfuncs/starknet.rs @@ -342,8 +342,9 @@ pub fn build_call_contract<'ctx, 'this>( IntegerType::new(context, 64).into(), )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -351,8 +352,7 @@ pub fn build_call_contract<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_class_hash_const<'ctx, 'this>( @@ -374,8 +374,7 @@ pub fn build_class_hash_const<'ctx, 'this>( 252, )?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } pub fn build_class_hash_try_from_felt252<'ctx, 'this>( @@ -402,14 +401,14 @@ pub fn build_class_hash_try_from_felt252<'ctx, 'this>( ))?; let is_in_range = entry.cmpi(context, CmpiPredicate::Ult, value, limit, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_range, [0, 1], [&[range_check, value], &[range_check]], location, - )); - Ok(()) + ) } pub fn build_contract_address_const<'ctx, 'this>( @@ -431,8 +430,7 @@ pub fn build_contract_address_const<'ctx, 'this>( 252, )?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } pub fn build_contract_address_try_from_felt252<'ctx, 'this>( @@ -459,14 +457,14 @@ pub fn build_contract_address_try_from_felt252<'ctx, 'this>( ))?; let is_in_range = entry.cmpi(context, CmpiPredicate::Ult, value, limit, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_range, [0, 1], [&[range_check, value], &[range_check]], location, - )); - Ok(()) + ) } pub fn build_storage_read<'ctx, 'this>( @@ -610,8 +608,9 @@ pub fn build_storage_read<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -619,8 +618,7 @@ pub fn build_storage_read<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_storage_write<'ctx, 'this>( @@ -772,8 +770,9 @@ pub fn build_storage_write<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -781,8 +780,7 @@ pub fn build_storage_write<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_storage_base_address_const<'ctx, 'this>( @@ -804,8 +802,7 @@ pub fn build_storage_base_address_const<'ctx, 'this>( 252, )?; - entry.append_operation(helper.br(0, &[value], location)); - Ok(()) + helper.br(entry, 0, &[value], location) } pub fn build_storage_base_address_from_felt252<'ctx, 'this>( @@ -845,8 +842,7 @@ pub fn build_storage_base_address_from_felt252<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[range_check, value], location)); - Ok(()) + helper.br(entry, 0, &[range_check, value], location) } pub fn build_storage_address_from_base_and_offset<'ctx, 'this>( @@ -861,8 +857,7 @@ pub fn build_storage_address_from_base_and_offset<'ctx, 'this>( let offset = entry.extui(entry.arg(1)?, entry.argument(0)?.r#type(), location)?; let addr = entry.addi(entry.arg(0)?, offset, location)?; - entry.append_operation(helper.br(0, &[addr], location)); - Ok(()) + helper.br(entry, 0, &[addr], location) } pub fn build_storage_address_try_from_felt252<'ctx, 'this>( @@ -889,14 +884,14 @@ pub fn build_storage_address_try_from_felt252<'ctx, 'this>( ))?; let is_in_range = entry.cmpi(context, CmpiPredicate::Ult, value, limit, location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_in_range, [0, 1], [&[range_check, value], &[range_check]], location, - )); - Ok(()) + ) } pub fn build_emit_event<'ctx, 'this>( @@ -1089,8 +1084,9 @@ pub fn build_emit_event<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1098,8 +1094,7 @@ pub fn build_emit_event<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_get_block_hash<'ctx, 'this>( @@ -1238,8 +1233,9 @@ pub fn build_get_block_hash<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1247,8 +1243,7 @@ pub fn build_get_block_hash<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_get_execution_info<'ctx, 'this>( @@ -1381,8 +1376,9 @@ pub fn build_get_execution_info<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1390,8 +1386,7 @@ pub fn build_get_execution_info<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_get_execution_info_v2<'ctx, 'this>( @@ -1524,8 +1519,9 @@ pub fn build_get_execution_info_v2<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1533,8 +1529,7 @@ pub fn build_get_execution_info_v2<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_deploy<'ctx, 'this>( @@ -1762,8 +1757,9 @@ pub fn build_deploy<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1788,8 +1784,7 @@ pub fn build_deploy<'ctx, 'this>( ], ], location, - )); - Ok(()) + ) } pub fn build_keccak<'ctx, 'this>( @@ -1938,8 +1933,9 @@ pub fn build_keccak<'ctx, 'this>( }; let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1947,8 +1943,7 @@ pub fn build_keccak<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_library_call<'ctx, 'this>( @@ -2118,8 +2113,9 @@ pub fn build_library_call<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2127,8 +2123,7 @@ pub fn build_library_call<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_replace_class<'ctx, 'this>( @@ -2268,8 +2263,9 @@ pub fn build_replace_class<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2277,8 +2273,7 @@ pub fn build_replace_class<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_send_message_to_l1<'ctx, 'this>( @@ -2443,8 +2438,9 @@ pub fn build_send_message_to_l1<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2452,8 +2448,7 @@ pub fn build_send_message_to_l1<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_sha256_process_block_syscall<'ctx, 'this>( @@ -2595,8 +2590,9 @@ pub fn build_sha256_process_block_syscall<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2604,8 +2600,7 @@ pub fn build_sha256_process_block_syscall<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_get_class_hash_at<'ctx, 'this>( @@ -2748,8 +2743,9 @@ pub fn build_get_class_hash_at<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2757,8 +2753,7 @@ pub fn build_get_class_hash_at<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/starknet/secp256.rs b/src/libfuncs/starknet/secp256.rs index 9aa3a1b1e..e4032e300 100644 --- a/src/libfuncs/starknet/secp256.rs +++ b/src/libfuncs/starknet/secp256.rs @@ -271,8 +271,9 @@ pub fn build_k1_new<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -280,8 +281,7 @@ pub fn build_k1_new<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_k1_add<'ctx, 'this>( @@ -484,8 +484,9 @@ pub fn build_k1_add<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -493,8 +494,7 @@ pub fn build_k1_add<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_k1_mul<'ctx, 'this>( @@ -697,8 +697,9 @@ pub fn build_k1_mul<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -706,8 +707,7 @@ pub fn build_k1_mul<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_k1_get_point_from_x<'ctx, 'this>( @@ -902,8 +902,9 @@ pub fn build_k1_get_point_from_x<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -911,8 +912,7 @@ pub fn build_k1_get_point_from_x<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_k1_get_xy<'ctx, 'this>( @@ -1149,8 +1149,9 @@ pub fn build_k1_get_xy<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1163,8 +1164,7 @@ pub fn build_k1_get_xy<'ctx, 'this>( ], ], location, - )); - Ok(()) + ) } pub fn build_r1_new<'ctx, 'this>( @@ -1367,8 +1367,9 @@ pub fn build_r1_new<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1376,8 +1377,7 @@ pub fn build_r1_new<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_r1_add<'ctx, 'this>( @@ -1580,8 +1580,9 @@ pub fn build_r1_add<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1589,8 +1590,7 @@ pub fn build_r1_add<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_r1_mul<'ctx, 'this>( @@ -1796,8 +1796,9 @@ pub fn build_r1_mul<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -1805,8 +1806,7 @@ pub fn build_r1_mul<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_r1_get_point_from_x<'ctx, 'this>( @@ -2002,8 +2002,9 @@ pub fn build_r1_get_point_from_x<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2011,8 +2012,7 @@ pub fn build_r1_get_point_from_x<'ctx, 'this>( &[remaining_gas, entry.argument(1)?.into(), payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_r1_get_xy<'ctx, 'this>( @@ -2251,8 +2251,9 @@ pub fn build_r1_get_xy<'ctx, 'this>( let remaining_gas = entry.load(context, location, gas_builtin_ptr, gas_ty)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2265,6 +2266,5 @@ pub fn build_r1_get_xy<'ctx, 'this>( ], ], location, - )); - Ok(()) + ) } diff --git a/src/libfuncs/starknet/testing.rs b/src/libfuncs/starknet/testing.rs index 2b9b024c4..dbf4f6a45 100644 --- a/src/libfuncs/starknet/testing.rs +++ b/src/libfuncs/starknet/testing.rs @@ -116,7 +116,5 @@ pub fn build<'ctx, 'this>( location, LoadStoreOptions::new(), ))?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } diff --git a/src/libfuncs/struct.rs b/src/libfuncs/struct.rs index 7e30cfb3b..8140ba0ba 100644 --- a/src/libfuncs/struct.rs +++ b/src/libfuncs/struct.rs @@ -71,9 +71,7 @@ pub fn build_construct<'ctx, 'this>( &fields, )?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `struct_construct` libfunc. @@ -117,7 +115,5 @@ pub fn build_deconstruct<'ctx, 'this>( fields.push(value); } - entry.append_operation(helper.br(0, &fields, location)); - - Ok(()) + helper.br(entry, 0, &fields, location) } diff --git a/src/libfuncs/uint128.rs b/src/libfuncs/uint128.rs index cb96ca053..a80bb1096 100644 --- a/src/libfuncs/uint128.rs +++ b/src/libfuncs/uint128.rs @@ -97,8 +97,7 @@ pub fn build_byte_reverse<'ctx, 'this>( let res = entry.append_op_result(ods::llvm::intr_bswap(context, arg1, location).into())?; - entry.append_operation(helper.br(0, &[bitwise, res], location)); - Ok(()) + helper.br(entry, 0, &[bitwise, res], location) } /// Generate MLIR operations for the `u128_const` libfunc. @@ -123,9 +122,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the `u128_safe_divmod` libfunc. @@ -146,8 +143,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u128_equal` libfunc. @@ -171,15 +167,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `u128s_from_felt252` libfunc. @@ -207,14 +202,14 @@ pub fn build_from_felt252<'ctx, 'this>( let msb_bits = entry.shrui(value, k128, location)?; let msb_bits = entry.trunci(msb_bits, IntegerType::new(context, 128).into(), location)?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, is_wide, [1, 0], [&[range_check, msb_bits, lsb_bits], &[range_check, lsb_bits]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u128_is_zero` libfunc. @@ -227,14 +222,12 @@ pub fn build_is_zero<'ctx, 'this>( _metadata: &mut MetadataStorage, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; - - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let value = entry.arg(0)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `u128_add` and `u128_sub` libfuncs. @@ -282,14 +275,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, overflow, [1, 0], [&[range_check, result], &[range_check, result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u128_sqrt` libfunc. @@ -427,8 +420,7 @@ pub fn build_square_root<'ctx, 'this>( let result = entry.trunci(result, i64_ty, location)?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u128_to_felt252` libfunc. @@ -447,8 +439,7 @@ pub fn build_to_felt252<'ctx, 'this>( location, )); - entry.append_operation(helper.br(0, &[op.result(0)?.into()], location)); - Ok(()) + helper.br(entry, 0, &[op.result(0)?.into()], location) } /// Generate MLIR operations for the `u128_guarantee_mul` libfunc. @@ -487,8 +478,7 @@ pub fn build_guarantee_mul<'ctx, 'this>( let guarantee = entry.append_op_result(llvm::undef(guarantee_type, location))?; - entry.append_operation(helper.br(0, &[result_hi, result_lo, guarantee], location)); - Ok(()) + helper.br(entry, 0, &[result_hi, result_lo, guarantee], location) } /// Generate MLIR operations for the `u128_guarantee_verify` libfunc. @@ -503,8 +493,7 @@ pub fn build_guarantee_verify<'ctx, 'this>( ) -> Result<()> { let range_check = super::increment_builtin_counter(context, entry, location, entry.arg(0)?)?; - entry.append_operation(helper.br(0, &[range_check], location)); - Ok(()) + helper.br(entry, 0, &[range_check], location) } #[cfg(test)] diff --git a/src/libfuncs/uint16.rs b/src/libfuncs/uint16.rs index 02aeae934..cab776dad 100644 --- a/src/libfuncs/uint16.rs +++ b/src/libfuncs/uint16.rs @@ -93,9 +93,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the u16 operation libfunc. @@ -143,14 +141,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op_overflow, [1, 0], [&[range_check, op_result], &[range_check, op_result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u16_eq` libfunc. @@ -167,9 +165,7 @@ pub fn build_equal<'ctx, 'this>( let cond = entry.cmpi(context, CmpiPredicate::Eq, arg0, arg1, location)?; - entry.append_operation(helper.cond_br(context, cond, [1, 0], [&[]; 2], location)); - - Ok(()) + helper.cond_br(context, entry, cond, [1, 0], [&[]; 2], location) } /// Generate MLIR operations for the `u16_is_zero` libfunc. @@ -181,19 +177,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; - - let const_0 = entry.append_op_result(arith::constant( - context, - IntegerAttribute::new(arg0.r#type(), 0).into(), - location, - ))?; - - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; + let value = entry.arg(0)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `u16_safe_divmod` libfunc. @@ -213,8 +202,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u16_widemul` libfunc. @@ -241,8 +229,7 @@ pub fn build_widemul<'ctx, 'this>( let rhs = entry.extui(rhs, target_type, location)?; let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u16_to_felt252` libfunc. @@ -266,9 +253,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u16_sqrt` libfunc. @@ -426,8 +411,7 @@ pub fn build_square_root<'ctx, 'this>( let result = entry.trunci(result, i8_ty, location)?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u16_from_felt252` libfunc. @@ -484,8 +468,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/libfuncs/uint256.rs b/src/libfuncs/uint256.rs index dacaf29b5..b5377e571 100644 --- a/src/libfuncs/uint256.rs +++ b/src/libfuncs/uint256.rs @@ -255,12 +255,12 @@ pub fn build_divmod<'ctx, 'this>( let op = entry.append_operation(llvm::undef(guarantee_type, location)); let guarantee = op.result(0)?.into(); - entry.append_operation(helper.br( + helper.br( + entry, 0, &[range_check, result_div, result_rem, guarantee], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u256_is_zero` libfunc. @@ -331,14 +331,14 @@ pub fn build_is_zero<'ctx, 'this>( .result(0)? .into(); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, val_is_zero, [0, 1], [&[], &[val_struct]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u256_sqrt` libfunc. @@ -634,8 +634,7 @@ pub fn build_square_root<'ctx, 'this>( .result(0)? .into(); - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u256_guarantee_inv_mod_n` libfunc. @@ -938,8 +937,9 @@ pub fn build_u256_guarantee_inv_mod_n<'ctx, 'this>( let op = entry.append_operation(llvm::undef(guarantee_type, location)); let guarantee = op.result(0)?.into(); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, condition, [0, 1], [ @@ -958,9 +958,7 @@ pub fn build_u256_guarantee_inv_mod_n<'ctx, 'this>( &[entry.arg(0)?, guarantee, guarantee], ], location, - )); - - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/uint32.rs b/src/libfuncs/uint32.rs index d7c3c5ade..9ada1a609 100644 --- a/src/libfuncs/uint32.rs +++ b/src/libfuncs/uint32.rs @@ -93,9 +93,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the u32 operation libfunc. @@ -143,14 +141,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op_overflow, [1, 0], [&[range_check, op_result], &[range_check, op_result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u32_eq` libfunc. @@ -173,15 +171,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `u32_is_zero` libfunc. @@ -193,15 +190,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `u32_safe_divmod` libfunc. @@ -221,8 +215,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u32_widemul` libfunc. @@ -249,8 +242,7 @@ pub fn build_widemul<'ctx, 'this>( let rhs = entry.extui(rhs, target_type, location)?; let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u32_to_felt252` libfunc. @@ -274,9 +266,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u32_sqrt` libfunc. @@ -414,8 +404,7 @@ pub fn build_square_root<'ctx, 'this>( let result = entry.trunci(result, i16_ty, location)?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u32_from_felt252` libfunc. @@ -467,8 +456,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/libfuncs/uint512.rs b/src/libfuncs/uint512.rs index 287a9a14b..5a4a8a98c 100644 --- a/src/libfuncs/uint512.rs +++ b/src/libfuncs/uint512.rs @@ -145,7 +145,8 @@ pub fn build_divmod_u256<'ctx, 'this>( let guarantee = entry.append_op_result(llvm::undef(guarantee_type, location))?; - entry.append_operation(helper.br( + helper.br( + entry, 0, &[ range_check, @@ -158,8 +159,7 @@ pub fn build_divmod_u256<'ctx, 'this>( guarantee, ], location, - )); - Ok(()) + ) } #[cfg(test)] diff --git a/src/libfuncs/uint64.rs b/src/libfuncs/uint64.rs index 4d95445a5..58e56b425 100644 --- a/src/libfuncs/uint64.rs +++ b/src/libfuncs/uint64.rs @@ -93,9 +93,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the u64 operation libfunc. @@ -143,14 +141,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op_overflow, [1, 0], [&[range_check, op_result], &[range_check, op_result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u64_eq` libfunc. @@ -167,9 +165,7 @@ pub fn build_equal<'ctx, 'this>( let cond = entry.cmpi(context, CmpiPredicate::Eq, arg0, arg1, location)?; - entry.append_operation(helper.cond_br(context, cond, [1, 0], [&[]; 2], location)); - - Ok(()) + helper.cond_br(context, entry, cond, [1, 0], [&[]; 2], location) } /// Generate MLIR operations for the `u64_is_zero` libfunc. @@ -187,9 +183,7 @@ pub fn build_is_zero<'ctx, 'this>( let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, condition, [0, 1], [&[], &[arg0]], location) } /// Generate MLIR operations for the `u64_safe_divmod` libfunc. @@ -209,8 +203,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u64_widemul` libfunc. @@ -237,8 +230,7 @@ pub fn build_widemul<'ctx, 'this>( let rhs = entry.extui(rhs, target_type, location)?; let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u64_to_felt252` libfunc. @@ -262,9 +254,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u64_sqrt` libfunc. @@ -399,8 +389,7 @@ pub fn build_square_root<'ctx, 'this>( let result = entry.trunci(result, i32_ty, location)?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u64_from_felt252` libfunc. @@ -452,8 +441,8 @@ pub fn build_from_felt252<'ctx, 'this>( let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_success, 0, &[range_check, value], location)?; + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/libfuncs/uint8.rs b/src/libfuncs/uint8.rs index eb0cd7fbe..8ea87162e 100644 --- a/src/libfuncs/uint8.rs +++ b/src/libfuncs/uint8.rs @@ -93,9 +93,7 @@ pub fn build_const<'ctx, 'this>( let value = entry.const_int_from_type(context, location, value, value_ty)?; - entry.append_operation(helper.br(0, &[value], location)); - - Ok(()) + helper.br(entry, 0, &[value], location) } /// Generate MLIR operations for the u8 operation libfunc. @@ -143,14 +141,14 @@ pub fn build_operation<'ctx, 'this>( 1, )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op_overflow, [1, 0], [&[range_check, op_result], &[range_check, op_result]], location, - )); - Ok(()) + ) } /// Generate MLIR operations for the `u8_eq` libfunc. @@ -173,15 +171,14 @@ pub fn build_equal<'ctx, 'this>( location, )); - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, op0.result(0)?.into(), [1, 0], [&[]; 2], location, - )); - - Ok(()) + ) } /// Generate MLIR operations for the `u8_is_zero` libfunc. @@ -193,15 +190,12 @@ pub fn build_is_zero<'ctx, 'this>( helper: &LibfuncHelper<'ctx, 'this>, _info: &SignatureOnlyConcreteLibfunc, ) -> Result<()> { - let arg0: Value = entry.arg(0)?; + let value = entry.arg(0)?; - let const_0 = entry.const_int_from_type(context, location, 0, arg0.r#type())?; + let k0 = entry.const_int_from_type(context, location, 0, value.r#type())?; + let is_zero = entry.cmpi(context, CmpiPredicate::Eq, value, k0, location)?; - let condition = entry.cmpi(context, CmpiPredicate::Eq, arg0, const_0, location)?; - - entry.append_operation(helper.cond_br(context, condition, [0, 1], [&[], &[arg0]], location)); - - Ok(()) + helper.cond_br(context, entry, is_zero, [0, 1], [&[], &[value]], location) } /// Generate MLIR operations for the `u8_safe_divmod` libfunc. @@ -221,8 +215,7 @@ pub fn build_divmod<'ctx, 'this>( let result_div = entry.append_op_result(arith::divui(lhs, rhs, location))?; let result_rem = entry.append_op_result(arith::remui(lhs, rhs, location))?; - entry.append_operation(helper.br(0, &[range_check, result_div, result_rem], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result_div, result_rem], location) } /// Generate MLIR operations for the `u8_widemul` libfunc. @@ -249,8 +242,7 @@ pub fn build_widemul<'ctx, 'this>( let rhs = entry.extui(rhs, target_type, location)?; let result = entry.muli(lhs, rhs, location)?; - entry.append_operation(helper.br(0, &[result], location)); - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u8_to_felt252` libfunc. @@ -274,9 +266,7 @@ pub fn build_to_felt252<'ctx, 'this>( let result = entry.extui(value, felt252_ty, location)?; - entry.append_operation(helper.br(0, &[result], location)); - - Ok(()) + helper.br(entry, 0, &[result], location) } /// Generate MLIR operations for the `u8_sqrt` libfunc. @@ -411,8 +401,7 @@ pub fn build_square_root<'ctx, 'this>( location, ))?; - entry.append_operation(helper.br(0, &[range_check, result], location)); - Ok(()) + helper.br(entry, 0, &[range_check, result], location) } /// Generate MLIR operations for the `u8_from_felt252` libfunc. @@ -463,9 +452,9 @@ pub fn build_from_felt252<'ctx, 'this>( )); let value = block_success.trunci(value, result_ty, location)?; - block_success.append_operation(helper.br(0, &[range_check, value], location)); + helper.br(block_success, 0, &[range_check, value], location)?; - block_failure.append_operation(helper.br(1, &[range_check], location)); + helper.br(block_failure, 1, &[range_check], location)?; Ok(()) } diff --git a/src/metadata.rs b/src/metadata.rs index 6f5038516..6a92ef75a 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -20,6 +20,7 @@ pub mod drop_overrides; pub mod dup_overrides; pub mod enum_snapshot_variants; pub mod gas; +pub mod profiler; pub mod realloc_bindings; pub mod runtime_bindings; pub mod tail_recursion; diff --git a/src/metadata/gas.rs b/src/metadata/gas.rs index 88b65cd54..24951655c 100644 --- a/src/metadata/gas.rs +++ b/src/metadata/gas.rs @@ -1,20 +1,18 @@ +use crate::{error::Result as NativeResult, native_panic}; use cairo_lang_runner::token_gas_cost; use cairo_lang_sierra::{ extensions::gas::CostTokenType, ids::FunctionId, program::{Program, StatementIdx}, }; -use cairo_lang_sierra_ap_change::{ap_change_info::ApChangeInfo, calc_ap_changes}; use cairo_lang_sierra_ap_change::{ + ap_change_info::ApChangeInfo, calc_ap_changes, compute::calc_ap_changes as linear_calc_ap_changes, ApChangeError, }; use cairo_lang_sierra_gas::{ compute_postcost_info, compute_precost_info, gas_info::GasInfo, CostError, }; use cairo_lang_utils::ordered_hash_map::OrderedHashMap; - -use crate::{error::Result as NativeResult, native_panic}; - use std::collections::BTreeMap; /// Holds global gas info. diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs new file mode 100644 index 000000000..918a3e5b9 --- /dev/null +++ b/src/metadata/profiler.rs @@ -0,0 +1,193 @@ +#![cfg(feature = "with-profiler")] + +use crate::{error::Result, utils::BlockExt}; +use cairo_lang_sierra::program::StatementIdx; +use melior::{ + dialect::{ + arith::{self, CmpiPredicate}, + llvm::{self, attributes::Linkage}, + ods, + }, + ir::{ + attribute::{FlatSymbolRefAttribute, StringAttribute, TypeAttribute}, + operation::OperationBuilder, + r#type::IntegerType, + Attribute, Block, Identifier, Location, Module, Region, Value, + }, + Context, +}; +use std::{cell::UnsafeCell, mem}; + +pub struct ProfilerMeta { + _private: (), +} + +impl ProfilerMeta { + pub fn new(context: &Context, module: &Module) -> Result { + // Generate the file descriptor holder. + module.body().append_operation( + ods::llvm::mlir_global( + context, + { + let region = Region::new(); + let block = region.append_block(Block::new(&[])); + + let null_ptr = block.append_op_result(llvm::zero( + llvm::r#type::pointer(context, 0), + Location::unknown(context), + ))?; + + block.append_operation(llvm::r#return( + Some(null_ptr), + Location::unknown(context), + )); + region + }, + TypeAttribute::new(llvm::r#type::pointer(context, 0)), + StringAttribute::new(context, "__profiler_callback"), + llvm::attributes::linkage(context, Linkage::Common), + Location::unknown(context), + ) + .into(), + ); + + Ok(Self { _private: () }) + } + + pub fn measure_timestamp<'c, 'a>( + &self, + context: &'c Context, + block: &'a Block<'c>, + location: Location<'c>, + ) -> Result<(Value<'c, 'a>, Value<'c, 'a>)> { + let i32_ty = IntegerType::new(context, 32).into(); + let i64_ty = IntegerType::new(context, 64).into(); + let k32 = block.const_int_from_type(context, location, 32, i64_ty)?; + + // edx:eax := TimeStampCounter (clock value) + // ecx := IA32_TSC_AUX[31:0] (core ID) + let value = block.append_op_result( + OperationBuilder::new("llvm.inline_asm", location) + .add_attributes(&[ + ( + Identifier::new(context, "asm_string"), + StringAttribute::new(context, "mfence\nrdtscp\nlfence").into(), + ), + ( + Identifier::new(context, "has_side_effects"), + Attribute::unit(context), + ), + ( + Identifier::new(context, "constraints"), + StringAttribute::new(context, "={edx},={eax},={ecx}").into(), + ), + ]) + .add_results(&[llvm::r#type::r#struct( + context, + &[i32_ty, i32_ty, i32_ty], + false, + )]) + .build()?, + )?; + let value_hi = block.extract_value(context, location, value, i32_ty, 0)?; + let value_lo = block.extract_value(context, location, value, i32_ty, 1)?; + let core_idx = block.extract_value(context, location, value, i32_ty, 2)?; + + let value_hi = block.extui(value_hi, i64_ty, location)?; + let value_lo = block.extui(value_lo, i64_ty, location)?; + let value = block.shli(value_hi, k32, location)?; + let value = block.append_op_result(arith::ori(value, value_lo, location))?; + + Ok((value, core_idx)) + } + + pub fn push_frame<'c>( + &self, + context: &'c Context, + block: &Block<'c>, + statement_idx: usize, + t0: (Value<'c, '_>, Value<'c, '_>), + t1: (Value<'c, '_>, Value<'c, '_>), + location: Location<'c>, + ) -> Result<()> { + // If core idx matches: + // Calculate time delta. + // Write statement idx and time delta. + // If core idx does not match: + // Write statement idx and -1. + + let i64_ty = IntegerType::new(context, 64).into(); + + let statement_idx = block.const_int_from_type(context, location, statement_idx, i64_ty)?; + let is_same_core = block.cmpi(context, CmpiPredicate::Eq, t0.1, t1.1, location)?; + + let delta_value = block.append_op_result(arith::subi(t1.0, t0.0, location))?; + let invalid_value = block.const_int_from_type(context, location, u64::MAX, i64_ty)?; + let delta_value = block.append_op_result(arith::select( + is_same_core, + delta_value, + invalid_value, + location, + ))?; + + let callback_ptr = block.append_op_result( + ods::llvm::mlir_addressof( + context, + llvm::r#type::pointer(context, 0), + FlatSymbolRefAttribute::new(context, "__profiler_callback"), + location, + ) + .into(), + )?; + let callback_ptr = block.load( + context, + location, + callback_ptr, + llvm::r#type::pointer(context, 0), + )?; + + block.append_operation( + ods::llvm::call( + context, + &[callback_ptr, statement_idx, delta_value], + location, + ) + .into(), + ); + Ok(()) + } +} + +thread_local! { + static PROFILER_IMPL: UnsafeCell = const { UnsafeCell::new(ProfilerImpl::new()) }; +} + +pub struct ProfilerImpl { + trace: Vec<(StatementIdx, u64)>, +} + +impl ProfilerImpl { + const fn new() -> Self { + Self { trace: Vec::new() } + } + + pub fn take() -> Vec<(StatementIdx, u64)> { + PROFILER_IMPL.with(|x| { + let x = unsafe { &mut *x.get() }; + + let mut trace = Vec::new(); + mem::swap(&mut x.trace, &mut trace); + + trace + }) + } + + pub extern "C" fn callback(statement_idx: u64, tick_delta: u64) { + PROFILER_IMPL.with(|x| { + let x = unsafe { &mut *x.get() }; + + x.trace + .push((StatementIdx(statement_idx as usize), tick_delta)); + }); + } +} From e9d592251d9d314b3a35fcf52269d0f3d79c31ed Mon Sep 17 00:00:00 2001 From: Esteve Soler Arderiu Date: Thu, 28 Nov 2024 14:36:37 +0100 Subject: [PATCH 02/27] Add support for `armv8`. --- src/metadata/profiler.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 918a3e5b9..2a0434c3f 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -54,6 +54,7 @@ impl ProfilerMeta { Ok(Self { _private: () }) } + #[cfg(target_arch = "x86_64")] pub fn measure_timestamp<'c, 'a>( &self, context: &'c Context, @@ -101,6 +102,39 @@ impl ProfilerMeta { Ok((value, core_idx)) } + #[cfg(target_arch = "aarch64")] + pub fn measure_timestamp<'c, 'a>( + &self, + context: &'c Context, + block: &'a Block<'c>, + location: Location<'c>, + ) -> Result<(Value<'c, 'a>, Value<'c, 'a>)> { + let i64_ty = IntegerType::new(context, 64).into(); + + let value = block.append_op_result( + OperationBuilder::new("llvm.inline_asm", location) + .add_attributes(&[ + ( + Identifier::new(context, "asm_string"), + StringAttribute::new(context, "isb\nmrs $0, CNTVCT_EL0\nisb").into(), + ), + ( + Identifier::new(context, "has_side_effects"), + Attribute::unit(context), + ), + ( + Identifier::new(context, "constraints"), + StringAttribute::new(context, "=r").into(), + ), + ]) + .add_results(&[i64_ty]) + .build()?, + )?; + let core_idx = block.const_int(context, location, 0, 64)?; + + Ok((value, core_idx)) + } + pub fn push_frame<'c>( &self, context: &'c Context, From 25bd806760dc5d70e4c629447856ace426a38879 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Thu, 29 May 2025 17:03:31 -0300 Subject: [PATCH 03/27] add support for aot and contract executor --- Cargo.toml | 2 +- profiling.txt | 784 +++++++++++++++++++++++++++++ src/bin/cairo-native-run.rs | 10 +- src/compiler.rs | 4 +- src/context.rs | 7 +- src/executor/aot.rs | 3 + src/executor/contract.rs | 3 + src/executor/jit.rs | 22 +- src/libfuncs.rs | 20 +- src/libfuncs/array.rs | 21 +- src/libfuncs/circuit.rs | 13 +- src/libfuncs/felt252_dict_entry.rs | 2 +- src/libfuncs/gas.rs | 2 +- src/libfuncs/starknet.rs | 6 +- src/metadata/profiler.rs | 145 ++++-- 15 files changed, 940 insertions(+), 104 deletions(-) create mode 100644 profiling.txt diff --git a/Cargo.toml b/Cargo.toml index ade97f07b..29fee6db4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,7 @@ scarb = ["build-cli", "dep:scarb-ui", "dep:scarb-metadata"] with-cheatcode = [] with-debug-utils = [] with-mem-tracing = [] -with-profiler = [] +with-libfunc-profiling = [] with-segfault-catcher = [] with-trace-dump = ["dep:sierra-emu"] diff --git a/profiling.txt b/profiling.txt new file mode 100644 index 000000000..e7e4b181b --- /dev/null +++ b/profiling.txt @@ -0,0 +1,784 @@ +alloc_local> + Samples : 17971 + Sum : 9456 + Average : 0.5261810695008625 + Deviation: 0.2559919763396106 + Quartiles: [0, 0, 1, 1, 2] + +finalize_locals + Samples : 17971 + Sum : 9619 + Average : 0.5352512381058372 + Deviation: 0.25565735577658016 + Quartiles: [0, 0, 1, 1, 2] + +disable_ap_tracking + Samples : 29303 + Sum : 15636 + Average : 0.5335972426031464 + Deviation: 0.2554234554364996 + Quartiles: [0, 0, 1, 1, 2] + +felt252_dict_new + Samples : 2 + Sum : 16 + Average : 8 + Deviation: 1 + Quartiles: [7, 7, 9, 9, 9] + +const_as_immediate> + Samples : 3 + Sum : 4 + Average : 1.3333333333333333 + Deviation: 0.2222222222222222 + Quartiles: [1, 1, 1, 2, 2] + +store_temp + Samples : 75706 + Sum : 40078 + Average : 0.5293900087179352 + Deviation: 0.25494818416773257 + Quartiles: [0, 0, 1, 1, 2] + +store_temp + Samples : 17979 + Sum : 9604 + Average : 0.5341787641136881 + Deviation: 0.256173710965694 + Quartiles: [0, 0, 1, 1, 2] + +store_temp + Samples : 59871 + Sum : 31870 + Average : 0.5323111356082243 + Deviation: 0.25560361624449 + Quartiles: [0, 0, 1, 1, 2] + +store_temp + Samples : 89921 + Sum : 47698 + Average : 0.5304433891971841 + Deviation: 0.2560571081507784 + Quartiles: [0, 0, 1, 1, 2] + +store_temp>> + Samples : 17970 + Sum : 9639 + Average : 0.5363939899833056 + Deviation: 0.2543516043713494 + Quartiles: [0, 0, 1, 1, 2] + +store_temp> + Samples : 50808 + Sum : 27185 + Average : 0.5350535348763974 + Deviation: 0.2589664945362802 + Quartiles: [0, 0, 1, 1, 2] + +enum_match, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>> + Samples : 1 + Sum : 2 + Average : 2 + Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +branch_align + Samples : 153550 + Sum : 81486 + Average : 0.5306805600781505 + Deviation: 0.2550632620083703 + Quartiles: [0, 0, 1, 1, 2] + +redeposit_gas + Samples : 27243 + Sum : 27243 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +struct_deconstruct, u32, Felt252Dict, u32, Unit>> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +drop + Samples : 17982 + Sum : 9482 + Average : 0.5273050828606384 + Deviation: 0.25759610745836947 + Quartiles: [0, 0, 1, 1, 2] + +drop + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +store_local> + Samples : 17969 + Sum : 9448 + Average : 0.5257944237297568 + Deviation: 0.2570145408538225 + Quartiles: [0, 0, 1, 1, 2] + +drop> + Samples : 2 + Sum : 112 + Average : 56 + Deviation: 4 + Quartiles: [54, 54, 58, 58, 58] + +drop>> + Samples : 2 + Sum : 1 + Average : 0.5 + Deviation: 0.25 + Quartiles: [0, 0, 1, 1, 1] + +alloc_local>> + Samples : 53836 + Sum : 28640 + Average : 0.5319860316516829 + Deviation: 0.2558124684872828 + Quartiles: [0, 0, 1, 1, 2] + +alloc_local> + Samples : 2 + Sum : 2 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +felt252_dict_new + Samples : 1 + Sum : 36 + Average : 36 + Deviation: 0 + Quartiles: [36, 36, 36, 36, 36] + +dup>> + Samples : 35936 + Sum : 25857 + Average : 0.7195291629563668 + Deviation: 0.2659209270213051 + Quartiles: [0, 0, 1, 1, 2] + +store_local> + Samples : 2 + Sum : 2 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +drop>>> + Samples : 53838 + Sum : 28537 + Average : 0.5300531223299528 + Deviation: 0.25478052765827014 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +store_temp + Samples : 35791 + Sum : 18952 + Average : 0.5295185940599592 + Deviation: 0.25320789040172226 + Quartiles: [0, 0, 1, 1, 2] + +store_temp> + Samples : 59649 + Sum : 31672 + Average : 0.5309728578852957 + Deviation: 0.25396951575154986 + Quartiles: [0, 0, 1, 1, 2] + +store_temp>> + Samples : 17897 + Sum : 9435 + Average : 0.5271833268145499 + Deviation: 0.25373108965213514 + Quartiles: [0, 0, 1, 1, 2] + +enum_match, core::dict::Felt252Dict::, core::integer::u32, ())>> + Samples : 1 + Sum : 4 + Average : 4 + Deviation: 0 + Quartiles: [4, 4, 4, 4, 4] + +struct_deconstruct, Felt252Dict, u32, Unit>> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +drop + Samples : 1 + Sum : 0 + Average : 0 + Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +drop> + Samples : 1 + Sum : 43 + Average : 43 + Deviation: 0 + Quartiles: [43, 43, 43, 43, 43] + +struct_construct> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +enum_init, 0> + Samples : 1 + Sum : 3 + Average : 3 + Deviation: 0 + Quartiles: [3, 3, 3, 3, 3] + +store_temp> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +drop>> + Samples : 1 + Sum : 5 + Average : 5 + Deviation: 0 + Quartiles: [5, 5, 5, 5, 5] + +drop>> + Samples : 2 + Sum : 21 + Average : 10.5 + Deviation: 72.25 + Quartiles: [2, 2, 19, 19, 19] + +alloc_local> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +array_new + Samples : 1 + Sum : 2 + Average : 2 + Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +const_as_immediate> + Samples : 12607 + Sum : 6587 + Average : 0.5224875069405885 + Deviation: 0.25409493073554057 + Quartiles: [0, 0, 1, 1, 2] + +store_temp + Samples : 29954 + Sum : 15998 + Average : 0.5340855979168058 + Deviation: 0.2562495361061688 + Quartiles: [0, 0, 1, 1, 2] + +array_append + Samples : 69 + Sum : 104 + Average : 1.5072463768115942 + Deviation: 0.24994749002310435 + Quartiles: [1, 1, 2, 2, 2] + +const_as_immediate> + Samples : 3390 + Sum : 1841 + Average : 0.5430678466076696 + Deviation: 0.2652543051313595 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 11951 + Sum : 6346 + Average : 0.5310015898251192 + Deviation: 0.2557329019302809 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 17910 + Sum : 9545 + Average : 0.5329424902289224 + Deviation: 0.25460993471613236 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 15255 + Sum : 7924 + Average : 0.5194362504097018 + Deviation: 0.254079787070113 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 1397 + Sum : 773 + Average : 0.5533285612025769 + Deviation: 0.2729255706445331 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 3338 + Sum : 1745 + Average : 0.5227681246255242 + Deviation: 0.2524774183728151 + Quartiles: [0, 0, 1, 1, 2] + +store_local> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +snapshot_take> + Samples : 1 + Sum : 2 + Average : 2 + Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +drop> + Samples : 1 + Sum : 2 + Average : 2 + Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +struct_construct + Samples : 3 + Sum : 3 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +enum_init>, 1> + Samples : 1 + Sum : 2 + Average : 2 + Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +withdraw_gas + Samples : 13622 + Sum : 13622 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +array_len + Samples : 17969 + Sum : 12448 + Average : 0.6927486226278591 + Deviation: 0.2623777141481627 + Quartiles: [0, 0, 1, 1, 2] + +dup + Samples : 37949 + Sum : 20268 + Average : 0.534085219636881 + Deviation: 0.2559003074757288 + Quartiles: [0, 0, 1, 1, 2] + +u32_overflowing_sub + Samples : 19295 + Sum : 11080 + Average : 0.5742420316144079 + Deviation: 0.25931061361559266 + Quartiles: [0, 0, 1, 1, 2] + +struct_construct, u32, Felt252Dict, u32, Unit>> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +enum_init, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>, 0> + Samples : 1 + Sum : 2 + Average : 2 + Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +store_temp, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>> + Samples : 1 + Sum : 2 + Average : 2 + Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +array_get + Samples : 17950 + Sum : 23619 + Average : 1.3158217270194985 + Deviation: 0.2927357453775038 + Quartiles: [0, 1, 1, 2, 3] + +store_temp> + Samples : 17968 + Sum : 9565 + Average : 0.5323352626892253 + Deviation: 0.2566347513567351 + Quartiles: [0, 0, 1, 1, 2] + +unbox + Samples : 17176 + Sum : 30899 + Average : 1.7989636702375407 + Deviation: 0.39362025811193857 + Quartiles: [0, 1, 2, 2, 3] + +rename + Samples : 17968 + Sum : 9534 + Average : 0.5306099732858415 + Deviation: 0.25618680513651393 + Quartiles: [0, 0, 1, 1, 2] + +enable_ap_tracking + Samples : 11330 + Sum : 6114 + Average : 0.5396293027360989 + Deviation: 0.25478432860300737 + Quartiles: [0, 0, 1, 1, 2] + +dup + Samples : 80292 + Sum : 42478 + Average : 0.5290439894385492 + Deviation: 0.2539140813114104 + Quartiles: [0, 0, 1, 1, 2] + +u8_eq + Samples : 69089 + Sum : 38660 + Average : 0.5595680933288946 + Deviation: 0.25701772368834486 + Quartiles: [0, 0, 1, 1, 2] + +jump + Samples : 61087 + Sum : 32261 + Average : 0.5281156383518588 + Deviation: 0.2549717843584459 + Quartiles: [0, 0, 1, 1, 2] + +u32_to_felt252 + Samples : 2002 + Sum : 1137 + Average : 0.567932067932068 + Deviation: 0.2563742451354904 + Quartiles: [0, 0, 1, 1, 2] + +felt252_dict_entry_get + Samples : 1755 + Sum : 18119 + Average : 10.324216524216524 + Deviation: 3.628786779328069 + Quartiles: [7, 9, 10, 11, 16] + +felt252_dict_entry_finalize + Samples : 2002 + Sum : 1133 + Average : 0.5659340659340659 + Deviation: 0.26263571593240775 + Quartiles: [0, 0, 1, 1, 2] + +drop + Samples : 27167 + Sum : 14386 + Average : 0.5295395148525784 + Deviation: 0.2546488217076357 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 19292 + Sum : 10256 + Average : 0.5316193240721543 + Deviation: 0.25501307341473545 + Quartiles: [0, 0, 1, 1, 2] + +u32_overflowing_add + Samples : 17968 + Sum : 10513 + Average : 0.5850957257346393 + Deviation: 0.25689495967005 + Quartiles: [0, 0, 1, 1, 2] + +felt252_dict_squash + Samples : 2 + Sum : 709 + Average : 354.5 + Deviation: 112560.25 + Quartiles: [19, 19, 690, 690, 690] + +store_temp> + Samples : 2 + Sum : 2 + Average : 1 + Deviation: 1 + Quartiles: [0, 0, 2, 2, 2] + +alloc_local> + Samples : 17897 + Sum : 9454 + Average : 0.528244957255406 + Deviation: 0.25423099816210254 + Quartiles: [0, 0, 1, 1, 2] + +alloc_local + Samples : 17897 + Sum : 9462 + Average : 0.5286919595462927 + Deviation: 0.253758544938931 + Quartiles: [0, 0, 1, 1, 2] + +drop> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +drop>> + Samples : 16572 + Sum : 8730 + Average : 0.5267921795800145 + Deviation: 0.2539889133639719 + Quartiles: [0, 0, 1, 1, 2] + +struct_construct, Felt252Dict, u32, Unit>> + Samples : 1 + Sum : 0 + Average : 0 + Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +enum_init, core::dict::Felt252Dict::, core::integer::u32, ())>, 0> + Samples : 1 + Sum : 5 + Average : 5 + Deviation: 0 + Quartiles: [5, 5, 5, 5, 5] + +store_temp, core::dict::Felt252Dict::, core::integer::u32, ())>> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +store_local + Samples : 17896 + Sum : 9397 + Average : 0.5250894054537327 + Deviation: 0.2531702535176324 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 3315 + Sum : 1776 + Average : 0.5357466063348416 + Deviation: 0.25354872613856855 + Quartiles: [0, 0, 1, 1, 2] + +array_new + Samples : 13 + Sum : 8 + Average : 0.6153846153846154 + Deviation: 0.23668639053254445 + Quartiles: [0, 0, 1, 1, 1] + +array_append + Samples : 12 + Sum : 21 + Average : 1.75 + Deviation: 0.5208333333333334 + Quartiles: [1, 1, 2, 2, 3] + +u8_to_felt252 + Samples : 13 + Sum : 5 + Average : 0.38461538461538464 + Deviation: 0.23668639053254442 + Quartiles: [0, 0, 0, 1, 1] + +store_local> + Samples : 1324 + Sum : 694 + Average : 0.5241691842900302 + Deviation: 0.25545814660326177 + Quartiles: [0, 0, 1, 1, 2] + +dup + Samples : 20541 + Sum : 10881 + Average : 0.5297210457134511 + Deviation: 0.25310867540982385 + Quartiles: [0, 0, 1, 1, 2] + +felt252_dict_entry_get + Samples : 19046 + Sum : 207205 + Average : 10.879187230914628 + Deviation: 6.024100063968452 + Quartiles: [7, 9, 10, 12, 19] + +felt252_dict_entry_finalize + Samples : 20540 + Sum : 11574 + Average : 0.5634858812074002 + Deviation: 0.2570698350003962 + Quartiles: [0, 0, 1, 1, 2] + +u8_is_zero + Samples : 1990 + Sum : 1024 + Average : 0.5145728643216081 + Deviation: 0.2558177823792311 + Quartiles: [0, 0, 1, 1, 2] + +drop> + Samples : 1325 + Sum : 719 + Average : 0.5426415094339623 + Deviation: 0.25723830544677345 + Quartiles: [0, 0, 1, 1, 2] + +rename + Samples : 37133 + Sum : 19586 + Average : 0.5274553631540678 + Deviation: 0.2540397828685643 + Quartiles: [0, 0, 1, 1, 2] + +rename + Samples : 37132 + Sum : 19515 + Average : 0.5255574706452656 + Deviation: 0.25435597221676814 + Quartiles: [0, 0, 1, 1, 2] + +rename> + Samples : 37133 + Sum : 19697 + Average : 0.5304446179947755 + Deviation: 0.25343582148908145 + Quartiles: [0, 0, 1, 1, 2] + +rename> + Samples : 37133 + Sum : 19668 + Average : 0.5296636415048609 + Deviation: 0.2535904855218947 + Quartiles: [0, 0, 1, 1, 2] + +rename + Samples : 37133 + Sum : 19751 + Average : 0.5318988500794442 + Deviation: 0.2535606014077435 + Quartiles: [0, 0, 1, 1, 2] + +store_temp> + Samples : 13 + Sum : 5 + Average : 0.38461538461538464 + Deviation: 0.23668639053254442 + Quartiles: [0, 0, 0, 1, 1] + +print + Samples : 12 + Sum : 885 + Average : 73.75 + Deviation: 159.02083333333334 + Quartiles: [63, 64, 69, 88, 101] + +const_as_immediate> + Samples : 9268 + Sum : 4882 + Average : 0.5267587397496764 + Deviation: 0.2531683030365071 + Quartiles: [0, 0, 1, 1, 2] + +u8_overflowing_sub + Samples : 8602 + Sum : 4959 + Average : 0.5764938386421763 + Deviation: 0.2578664327102487 + Quartiles: [0, 0, 1, 1, 2] + +u8_overflowing_add + Samples : 667 + Sum : 383 + Average : 0.5742128935532234 + Deviation: 0.280474455425957 + Quartiles: [0, 0, 1, 1, 2] + +const_as_immediate> + Samples : 5299 + Sum : 2842 + Average : 0.5363276089828269 + Deviation: 0.25245460186278157 + Quartiles: [0, 0, 1, 1, 2] + +felt252_sub + Samples : 2648 + Sum : 1578 + Average : 0.5959214501510574 + Deviation: 0.26421297268188015 + Quartiles: [0, 0, 1, 1, 2] + +rename + Samples : 15245 + Sum : 8124 + Average : 0.5328960314857331 + Deviation: 0.2529847582951311 + Quartiles: [0, 0, 1, 1, 2] + +felt252_add + Samples : 2651 + Sum : 1574 + Average : 0.5937382119954734 + Deviation: 0.26007395485445434 + Quartiles: [0, 0, 1, 1, 2] + +felt252_dict_squash + Samples : 1 + Sum : 2 + Average : 2 + Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +store_temp> + Samples : 1 + Sum : 1 + Average : 1 + Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index e06725e66..e0af48f0e 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -46,10 +46,10 @@ struct Args { #[arg(short = 'O', long, default_value_t = 0)] opt_level: u8, - #[cfg(feature = "with-profiler")] + #[cfg(feature = "with-libfunc-profiling")] #[arg(long)] /// The output path for the libfunc profilling results - profiler_output: Option, + profiler_output: PathBuf, #[cfg(feature = "with-trace-dump")] #[arg(long)] @@ -193,8 +193,8 @@ fn main() -> anyhow::Result<()> { println!("Remaining gas: {gas}"); } - #[cfg(feature = "with-profiler")] - if let Some(profiler_output) = args.profiler_output { + #[cfg(feature = "with-libfunc-profiling")] + { use cairo_lang_sierra::{ids::ConcreteLibfuncId, program::Statement}; use std::{collections::HashMap, fs::File, io::Write}; @@ -279,7 +279,7 @@ fn main() -> anyhow::Result<()> { .unwrap() }); - let mut output = File::create(profiler_output)?; + let mut output = File::create(args.profiler_output)?; for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in trace { writeln!(output, "{libfunc_id}")?; diff --git a/src/compiler.rs b/src/compiler.rs index 84ce14bd2..8958aac65 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -613,7 +613,7 @@ fn compile_func( .map(|x| vec![Cell::new(None); x.results.len()]) .collect::>(), - #[cfg(feature = "with-profiler")] + #[cfg(feature = "with-libfunc-profiling")] profiler: match libfunc { CoreConcreteLibfunc::FunctionCall(_) => { // Tail-recursive function calls are broken. Also it'd include the entire function which @@ -646,7 +646,7 @@ fn compile_func( libfunc_name ); - #[cfg(feature = "with-profiler")] + #[cfg(feature = "with-libfunc-profiling")] if let Some((profiler_meta, _, _)) = helper.profiler.take() { metadata.insert(profiler_meta); } diff --git a/src/context.rs b/src/context.rs index 045ffe256..2e1bbfcf0 100644 --- a/src/context.rs +++ b/src/context.rs @@ -164,11 +164,8 @@ impl NativeContext { // already some metadata of the same type. metadata.insert(gas_metadata); - #[cfg(feature = "with-profiler")] - metadata.insert(crate::metadata::profiler::ProfilerMeta::new( - &self.context, - &module, - )?); + #[cfg(feature = "with-libfunc-profiling")] + metadata.insert(crate::metadata::profiler::ProfilerMeta::new()?); // Create the Sierra program registry let registry = ProgramRegistry::::new(program)?; diff --git a/src/executor/aot.rs b/src/executor/aot.rs index 7de2cb4f8..3c864d171 100644 --- a/src/executor/aot.rs +++ b/src/executor/aot.rs @@ -60,6 +60,9 @@ impl AotNativeExecutor { #[cfg(feature = "with-trace-dump")] crate::metadata::trace_dump::setup_runtime(|name| executor.find_symbol_ptr(name)); + #[cfg(feature = "with-libfunc-profiling")] + crate::metadata::profiler::setup_runtime(|name| executor.find_symbol_ptr(name)); + executor } diff --git a/src/executor/contract.rs b/src/executor/contract.rs index 6dc417e7b..3217443ba 100644 --- a/src/executor/contract.rs +++ b/src/executor/contract.rs @@ -285,6 +285,9 @@ impl AotContractExecutor { #[cfg(feature = "with-trace-dump")] crate::metadata::trace_dump::setup_runtime(|name| executor.find_symbol_ptr(name)); + #[cfg(feature = "with-libfunc-profiling")] + crate::metadata::profiler::setup_runtime(|name| executor.find_symbol_ptr(name)); + Ok(Some(executor)) } diff --git a/src/executor/jit.rs b/src/executor/jit.rs index 3758656dd..f7cbe58c7 100644 --- a/src/executor/jit.rs +++ b/src/executor/jit.rs @@ -71,6 +71,9 @@ impl<'m> JitNativeExecutor<'m> { #[cfg(feature = "with-trace-dump")] crate::metadata::trace_dump::setup_runtime(|name| executor.find_symbol_ptr(name)); + #[cfg(feature = "with-libfunc-profiling")] + crate::metadata::profiler::setup_runtime(|name| executor.find_symbol_ptr(name)); + Ok(executor) } @@ -94,9 +97,6 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - #[cfg(feature = "with-profiler")] - self.setup_profiling(); - super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -121,9 +121,6 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - #[cfg(feature = "with-profiler")] - self.setup_profiling(); - super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -147,9 +144,6 @@ impl<'m> JitNativeExecutor<'m> { .get_initial_available_gas(function_id, gas) .map_err(crate::error::Error::GasMetadataError)?; - #[cfg(feature = "with-profiler")] - self.setup_profiling(); - ContractExecutionResult::from_execution_result(super::invoke_dynamic( &self.registry, self.find_function_ptr(function_id), @@ -201,14 +195,4 @@ impl<'m> JitNativeExecutor<'m> { .map(|ptr| unsafe { transmute(ptr as *const ()) }) } } - - #[cfg(feature = "with-profiler")] - fn setup_profiling(&self) { - unsafe { - let callback_ptr: *mut extern "C" fn(u64, u64) = - self.engine.lookup("__profiler_callback").cast(); - - *callback_ptr = crate::metadata::profiler::ProfilerImpl::callback; - } - } } diff --git a/src/libfuncs.rs b/src/libfuncs.rs index b22b050b0..94d722531 100644 --- a/src/libfuncs.rs +++ b/src/libfuncs.rs @@ -280,7 +280,7 @@ where pub branches: Vec<(&'this Block<'ctx>, Vec>)>, pub results: Vec>>>>, - #[cfg(feature = "with-profiler")] + #[cfg(feature = "with-libfunc-profiling")] pub profiler: Option<( crate::metadata::profiler::ProfilerMeta, cairo_lang_sierra::program::StatementIdx, @@ -357,8 +357,13 @@ where }) .collect::>(); - #[cfg(feature = "with-profiler")] - self.push_profiler_frame(unsafe { self.context().to_ref() }, block, location)?; + #[cfg(feature = "with-libfunc-profiling")] + self.push_profiler_frame( + unsafe { self.context().to_ref() }, + self.module, + block, + location, + )?; block.append_operation(cf::br(successor, &destination_operands, location)); Ok(()) @@ -420,8 +425,8 @@ where (*successor, destination_operands) }; - #[cfg(feature = "with-profiler")] - self.push_profiler_frame(context, block, location)?; + #[cfg(feature = "with-libfunc-profiling")] + self.push_profiler_frame(context, self.module, block, location)?; block.append_operation(cf::cond_br( context, @@ -435,10 +440,11 @@ where Ok(()) } - #[cfg(feature = "with-profiler")] + #[cfg(feature = "with-libfunc-profiling")] fn push_profiler_frame( &self, context: &'ctx Context, + module: &'this Module, block: &'this Block<'ctx>, location: Location<'ctx>, ) -> Result<()> { @@ -446,7 +452,7 @@ where let t0 = *t0; let t1 = profiler_meta.measure_timestamp(context, block, location)?; - profiler_meta.push_frame(context, block, statement_idx.0, t0, t1, location)?; + profiler_meta.push_frame(context, module, block, statement_idx.0, t0, t1, location)?; } Ok(()) diff --git a/src/libfuncs/array.rs b/src/libfuncs/array.rs index 5cd7dd87d..f43130867 100644 --- a/src/libfuncs/array.rs +++ b/src/libfuncs/array.rs @@ -719,8 +719,7 @@ pub fn build_append<'ctx, 'this>( )?; entry.store(context, location, max_len_ptr, array_end)?; - helper.br(entry, 0, &[array_obj], location); - Ok(()) + helper.br(entry, 0, &[array_obj], location) } #[derive(Clone, Copy)] @@ -937,7 +936,7 @@ fn build_pop<'ctx, 'this, const CONSUME: bool, const REVERSE: bool>( branch_values.push(array_obj); branch_values.push(target_ptr); - helper.br(valid_block, 0, &branch_values, location); + helper.br(valid_block, 0, &branch_values, location)?; } { @@ -952,8 +951,10 @@ fn build_pop<'ctx, 'this, const CONSUME: bool, const REVERSE: bool>( branch_values.push(array_obj); } - helper.br(error_block, 1, &branch_values, location) + helper.br(error_block, 1, &branch_values, location)?; } + + Ok(()) } /// Generate MLIR operations for the `array_get` libfunc. @@ -1068,7 +1069,7 @@ pub fn build_get<'ctx, 'this>( entry.argument(1)?.into(), )?; - helper.br(valid_block, 0, &[range_check, target_ptr], location); + helper.br(valid_block, 0, &[range_check, target_ptr], location)?; } { @@ -1083,8 +1084,10 @@ pub fn build_get<'ctx, 'this>( entry.argument(1)?.into(), )?; - helper.br(error_block, 1, &[range_check], location) + helper.br(error_block, 1, &[range_check], location)?; } + + Ok(()) } /// Generate MLIR operations for the `array_slice` libfunc. @@ -1147,7 +1150,7 @@ pub fn build_slice<'ctx, 'this>( let array_obj = valid_block.insert_value(context, location, array_obj, array_start, 1)?; let array_obj = valid_block.insert_value(context, location, array_obj, array_end, 2)?; - helper.br(valid_block, 0, &[range_check, array_obj], location); + helper.br(valid_block, 0, &[range_check, array_obj], location)?; } { @@ -1162,8 +1165,10 @@ pub fn build_slice<'ctx, 'this>( array_obj, )?; - helper.br(error_block, 1, &[range_check], location) + helper.br(error_block, 1, &[range_check], location)?; } + + Ok(()) } /// Generate MLIR operations for the `array_len` libfunc. diff --git a/src/libfuncs/circuit.rs b/src/libfuncs/circuit.rs index 1418f692c..48a0d39e4 100644 --- a/src/libfuncs/circuit.rs +++ b/src/libfuncs/circuit.rs @@ -233,7 +233,7 @@ fn build_add_input<'ctx, 'this>( // If not last insert, then return accumulator { - helper.br(middle_insert_block, 1, &[accumulator], location); + helper.br(middle_insert_block, 1, &[accumulator], location)?; } // If is last insert, then return accumulator.pointer @@ -247,7 +247,7 @@ fn build_add_input<'ctx, 'this>( 1, )?; - helper.br(last_insert_block, 0, &[inputs_ptr], location); + helper.br(last_insert_block, 0, &[inputs_ptr], location)?; } Ok(()) @@ -853,9 +853,7 @@ fn build_u96_single_limb_less_than_guarantee_verify<'ctx, 'this>( // calcualte diff between limbs let diff = entry.append_op_result(arith::subi(modulus_limb, gate_limb, location))?; - helper.br(entry, 0, &[diff], location); - - Ok(()) + helper.br(entry, 0, &[diff], location) } /// Generate MLIR operations for the `get_circuit_output` libfunc. @@ -941,7 +939,7 @@ fn build_get_output<'ctx, 'this>( )?; } - helper.br(entry, 0, &[output_struct, guarantee], location); + helper.br(entry, 0, &[output_struct, guarantee], location)?; Ok(()) } @@ -1185,8 +1183,7 @@ fn build_into_u96_guarantee<'ctx, 'this>( dst = entry.addi(dst, klower, location)? } - helper.br(entry, 0, &[dst], location); - Ok(()) + helper.br(entry, 0, &[dst], location) } #[cfg(test)] diff --git a/src/libfuncs/felt252_dict_entry.rs b/src/libfuncs/felt252_dict_entry.rs index 8f493470c..fe91f5f71 100644 --- a/src/libfuncs/felt252_dict_entry.rs +++ b/src/libfuncs/felt252_dict_entry.rs @@ -120,7 +120,7 @@ pub fn build_get<'ctx, 'this>( branches: Vec::new(), results: Vec::new(), - #[cfg(feature = "with-profiler")] + #[cfg(feature = "with-libfunc-profiling")] profiler: helper.profiler.clone(), }; diff --git a/src/libfuncs/gas.rs b/src/libfuncs/gas.rs index 013321a16..d164437b9 100644 --- a/src/libfuncs/gas.rs +++ b/src/libfuncs/gas.rs @@ -17,7 +17,7 @@ use cairo_lang_sierra::{ }; use melior::{ dialect::{arith::CmpiPredicate, ods}, - ir::{r#type::IntegerType, Block, BlockLike, Location, Value}, + ir::{r#type::IntegerType, Block, Location, Value}, Context, }; diff --git a/src/libfuncs/starknet.rs b/src/libfuncs/starknet.rs index 009115d9e..815d4ae63 100644 --- a/src/libfuncs/starknet.rs +++ b/src/libfuncs/starknet.rs @@ -2320,8 +2320,9 @@ pub fn build_meta_tx_v0<'ctx, 'this>( IntegerType::new(context, 64).into(), )?; - entry.append_operation(helper.cond_br( + helper.cond_br( context, + entry, result_tag, [1, 0], [ @@ -2329,8 +2330,7 @@ pub fn build_meta_tx_v0<'ctx, 'this>( &[remaining_gas, entry.arg(1)?, payload_ok], ], location, - )); - Ok(()) + ) } pub fn build_replace_class<'ctx, 'this>( diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index d8da9c9fc..efd4913cd 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -1,11 +1,14 @@ -#![cfg(feature = "with-profiler")] +#![cfg(feature = "with-libfunc-profiling")] -use crate::{error::Result, utils::BlockExt}; +use crate::{ + error::{Error, Result}, + utils::BlockExt, +}; use cairo_lang_sierra::program::StatementIdx; use melior::{ dialect::{ arith::{self, CmpiPredicate}, - llvm::{self, attributes::Linkage}, + llvm::{self}, ods, }, ir::{ @@ -16,45 +19,94 @@ use melior::{ }, Context, }; -use std::{cell::UnsafeCell, mem}; +use std::{ + cell::{RefCell, UnsafeCell}, + collections::HashSet, + ffi::c_void, + mem, +}; + +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub enum ProfilerBinding { + CallBack, +} + +impl ProfilerBinding { + pub const fn symbol(self) -> &'static str { + match self { + ProfilerBinding::CallBack => "cairo_native__profiler__callback", + } + } + + const fn function_ptr(self) -> *const () { + match self { + ProfilerBinding::CallBack => ProfilerImpl::callback as *const (), + } + } +} #[derive(Clone)] pub struct ProfilerMeta { + active_map: RefCell>, _private: (), } impl ProfilerMeta { - pub fn new(context: &Context, module: &Module) -> Result { - // Generate the file descriptor holder. - module.body().append_operation( - ods::llvm::mlir_global( + pub fn new() -> Result { + Ok(Self { + active_map: RefCell::new(HashSet::new()), + _private: (), + }) + } + + /// Register the global for the given binding, if not yet registered, and return + /// a pointer to the stored value. + /// + /// For the function to be available, `setup_runtime` must be called before running the module + fn build_function<'c, 'a>( + &self, + context: &'c Context, + module: &Module, + block: &'a Block<'c>, + location: Location<'c>, + binding: ProfilerBinding, + ) -> Result> { + if !self.active_map.borrow().contains(&binding) { + self.active_map.borrow_mut().insert(binding); + + module.body().append_operation( + ods::llvm::mlir_global( + context, + Region::new(), + TypeAttribute::new(llvm::r#type::pointer(context, 0)), + StringAttribute::new(context, binding.symbol()), + Attribute::parse(context, "#llvm.linkage") + .ok_or(Error::ParseAttributeError)?, + location, + ) + .into(), + ); + } + + let global_address = block.append_op_result( + ods::llvm::mlir_addressof( context, - { - let region = Region::new(); - let block = region.append_block(Block::new(&[])); - - let null_ptr = block.append_op_result(llvm::zero( - llvm::r#type::pointer(context, 0), - Location::unknown(context), - ))?; - - block.append_operation(llvm::r#return( - Some(null_ptr), - Location::unknown(context), - )); - region - }, - TypeAttribute::new(llvm::r#type::pointer(context, 0)), - StringAttribute::new(context, "__profiler_callback"), - llvm::attributes::linkage(context, Linkage::Common), - Location::unknown(context), + llvm::r#type::pointer(context, 0), + FlatSymbolRefAttribute::new(context, binding.symbol()), + location, ) .into(), - ); + )?; - Ok(Self { _private: () }) + block.load( + context, + location, + global_address, + llvm::r#type::pointer(context, 0), + ) } + /// Get the timestamp #[cfg(target_arch = "x86_64")] pub fn measure_timestamp<'c, 'a>( &self, @@ -103,6 +155,7 @@ impl ProfilerMeta { Ok((value, core_idx)) } + /// Get the timestamp #[cfg(target_arch = "aarch64")] pub fn measure_timestamp<'c, 'a>( &self, @@ -136,9 +189,14 @@ impl ProfilerMeta { Ok((value, core_idx)) } + /// Receives two timestamps, if they were originated in the same statement index + /// the delta time between these two is calculated. If not, then the delta time is + /// assigned to -1. Then it pushes the frame, which is made of the statement index + /// the delta time. pub fn push_frame<'c>( &self, context: &'c Context, + module: &Module, block: &Block<'c>, statement_idx: usize, t0: (Value<'c, '_>, Value<'c, '_>), @@ -165,21 +223,8 @@ impl ProfilerMeta { location, ))?; - let callback_ptr = block.append_op_result( - ods::llvm::mlir_addressof( - context, - llvm::r#type::pointer(context, 0), - FlatSymbolRefAttribute::new(context, "__profiler_callback"), - location, - ) - .into(), - )?; - let callback_ptr = block.load( - context, - location, - callback_ptr, - llvm::r#type::pointer(context, 0), - )?; + let callback_ptr = + self.build_function(context, module, block, location, ProfilerBinding::CallBack)?; block.append_operation( ods::llvm::call( @@ -217,6 +262,7 @@ impl ProfilerImpl { }) } + // Push a profiler frame pub extern "C" fn callback(statement_idx: u64, tick_delta: u64) { PROFILER_IMPL.with(|x| { let x = unsafe { &mut *x.get() }; @@ -226,3 +272,14 @@ impl ProfilerImpl { }); } } + +pub fn setup_runtime(find_symbol_ptr: impl Fn(&str) -> Option<*mut c_void>) { + let bindings = &[ProfilerBinding::CallBack]; + + for binding in bindings { + if let Some(global) = find_symbol_ptr(binding.symbol()) { + let global = global.cast::<*const ()>(); + unsafe { *global = binding.function_ptr() }; + } + } +} From 87ace62305e888dd0e9da52898fa15360a71af20 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Thu, 29 May 2025 17:04:20 -0300 Subject: [PATCH 04/27] remove unneeded file --- profiling.txt | 784 -------------------------------------------------- 1 file changed, 784 deletions(-) delete mode 100644 profiling.txt diff --git a/profiling.txt b/profiling.txt deleted file mode 100644 index e7e4b181b..000000000 --- a/profiling.txt +++ /dev/null @@ -1,784 +0,0 @@ -alloc_local> - Samples : 17971 - Sum : 9456 - Average : 0.5261810695008625 - Deviation: 0.2559919763396106 - Quartiles: [0, 0, 1, 1, 2] - -finalize_locals - Samples : 17971 - Sum : 9619 - Average : 0.5352512381058372 - Deviation: 0.25565735577658016 - Quartiles: [0, 0, 1, 1, 2] - -disable_ap_tracking - Samples : 29303 - Sum : 15636 - Average : 0.5335972426031464 - Deviation: 0.2554234554364996 - Quartiles: [0, 0, 1, 1, 2] - -felt252_dict_new - Samples : 2 - Sum : 16 - Average : 8 - Deviation: 1 - Quartiles: [7, 7, 9, 9, 9] - -const_as_immediate> - Samples : 3 - Sum : 4 - Average : 1.3333333333333333 - Deviation: 0.2222222222222222 - Quartiles: [1, 1, 1, 2, 2] - -store_temp - Samples : 75706 - Sum : 40078 - Average : 0.5293900087179352 - Deviation: 0.25494818416773257 - Quartiles: [0, 0, 1, 1, 2] - -store_temp - Samples : 17979 - Sum : 9604 - Average : 0.5341787641136881 - Deviation: 0.256173710965694 - Quartiles: [0, 0, 1, 1, 2] - -store_temp - Samples : 59871 - Sum : 31870 - Average : 0.5323111356082243 - Deviation: 0.25560361624449 - Quartiles: [0, 0, 1, 1, 2] - -store_temp - Samples : 89921 - Sum : 47698 - Average : 0.5304433891971841 - Deviation: 0.2560571081507784 - Quartiles: [0, 0, 1, 1, 2] - -store_temp>> - Samples : 17970 - Sum : 9639 - Average : 0.5363939899833056 - Deviation: 0.2543516043713494 - Quartiles: [0, 0, 1, 1, 2] - -store_temp> - Samples : 50808 - Sum : 27185 - Average : 0.5350535348763974 - Deviation: 0.2589664945362802 - Quartiles: [0, 0, 1, 1, 2] - -enum_match, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>> - Samples : 1 - Sum : 2 - Average : 2 - Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -branch_align - Samples : 153550 - Sum : 81486 - Average : 0.5306805600781505 - Deviation: 0.2550632620083703 - Quartiles: [0, 0, 1, 1, 2] - -redeposit_gas - Samples : 27243 - Sum : 27243 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -struct_deconstruct, u32, Felt252Dict, u32, Unit>> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -drop - Samples : 17982 - Sum : 9482 - Average : 0.5273050828606384 - Deviation: 0.25759610745836947 - Quartiles: [0, 0, 1, 1, 2] - -drop - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -store_local> - Samples : 17969 - Sum : 9448 - Average : 0.5257944237297568 - Deviation: 0.2570145408538225 - Quartiles: [0, 0, 1, 1, 2] - -drop> - Samples : 2 - Sum : 112 - Average : 56 - Deviation: 4 - Quartiles: [54, 54, 58, 58, 58] - -drop>> - Samples : 2 - Sum : 1 - Average : 0.5 - Deviation: 0.25 - Quartiles: [0, 0, 1, 1, 1] - -alloc_local>> - Samples : 53836 - Sum : 28640 - Average : 0.5319860316516829 - Deviation: 0.2558124684872828 - Quartiles: [0, 0, 1, 1, 2] - -alloc_local> - Samples : 2 - Sum : 2 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -felt252_dict_new - Samples : 1 - Sum : 36 - Average : 36 - Deviation: 0 - Quartiles: [36, 36, 36, 36, 36] - -dup>> - Samples : 35936 - Sum : 25857 - Average : 0.7195291629563668 - Deviation: 0.2659209270213051 - Quartiles: [0, 0, 1, 1, 2] - -store_local> - Samples : 2 - Sum : 2 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -drop>>> - Samples : 53838 - Sum : 28537 - Average : 0.5300531223299528 - Deviation: 0.25478052765827014 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -store_temp - Samples : 35791 - Sum : 18952 - Average : 0.5295185940599592 - Deviation: 0.25320789040172226 - Quartiles: [0, 0, 1, 1, 2] - -store_temp> - Samples : 59649 - Sum : 31672 - Average : 0.5309728578852957 - Deviation: 0.25396951575154986 - Quartiles: [0, 0, 1, 1, 2] - -store_temp>> - Samples : 17897 - Sum : 9435 - Average : 0.5271833268145499 - Deviation: 0.25373108965213514 - Quartiles: [0, 0, 1, 1, 2] - -enum_match, core::dict::Felt252Dict::, core::integer::u32, ())>> - Samples : 1 - Sum : 4 - Average : 4 - Deviation: 0 - Quartiles: [4, 4, 4, 4, 4] - -struct_deconstruct, Felt252Dict, u32, Unit>> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -drop - Samples : 1 - Sum : 0 - Average : 0 - Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -drop> - Samples : 1 - Sum : 43 - Average : 43 - Deviation: 0 - Quartiles: [43, 43, 43, 43, 43] - -struct_construct> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -enum_init, 0> - Samples : 1 - Sum : 3 - Average : 3 - Deviation: 0 - Quartiles: [3, 3, 3, 3, 3] - -store_temp> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -drop>> - Samples : 1 - Sum : 5 - Average : 5 - Deviation: 0 - Quartiles: [5, 5, 5, 5, 5] - -drop>> - Samples : 2 - Sum : 21 - Average : 10.5 - Deviation: 72.25 - Quartiles: [2, 2, 19, 19, 19] - -alloc_local> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -array_new - Samples : 1 - Sum : 2 - Average : 2 - Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -const_as_immediate> - Samples : 12607 - Sum : 6587 - Average : 0.5224875069405885 - Deviation: 0.25409493073554057 - Quartiles: [0, 0, 1, 1, 2] - -store_temp - Samples : 29954 - Sum : 15998 - Average : 0.5340855979168058 - Deviation: 0.2562495361061688 - Quartiles: [0, 0, 1, 1, 2] - -array_append - Samples : 69 - Sum : 104 - Average : 1.5072463768115942 - Deviation: 0.24994749002310435 - Quartiles: [1, 1, 2, 2, 2] - -const_as_immediate> - Samples : 3390 - Sum : 1841 - Average : 0.5430678466076696 - Deviation: 0.2652543051313595 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 11951 - Sum : 6346 - Average : 0.5310015898251192 - Deviation: 0.2557329019302809 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 17910 - Sum : 9545 - Average : 0.5329424902289224 - Deviation: 0.25460993471613236 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 15255 - Sum : 7924 - Average : 0.5194362504097018 - Deviation: 0.254079787070113 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 1397 - Sum : 773 - Average : 0.5533285612025769 - Deviation: 0.2729255706445331 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 3338 - Sum : 1745 - Average : 0.5227681246255242 - Deviation: 0.2524774183728151 - Quartiles: [0, 0, 1, 1, 2] - -store_local> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -snapshot_take> - Samples : 1 - Sum : 2 - Average : 2 - Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -drop> - Samples : 1 - Sum : 2 - Average : 2 - Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -struct_construct - Samples : 3 - Sum : 3 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -enum_init>, 1> - Samples : 1 - Sum : 2 - Average : 2 - Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -withdraw_gas - Samples : 13622 - Sum : 13622 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -array_len - Samples : 17969 - Sum : 12448 - Average : 0.6927486226278591 - Deviation: 0.2623777141481627 - Quartiles: [0, 0, 1, 1, 2] - -dup - Samples : 37949 - Sum : 20268 - Average : 0.534085219636881 - Deviation: 0.2559003074757288 - Quartiles: [0, 0, 1, 1, 2] - -u32_overflowing_sub - Samples : 19295 - Sum : 11080 - Average : 0.5742420316144079 - Deviation: 0.25931061361559266 - Quartiles: [0, 0, 1, 1, 2] - -struct_construct, u32, Felt252Dict, u32, Unit>> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -enum_init, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>, 0> - Samples : 1 - Sum : 2 - Average : 2 - Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -store_temp, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>> - Samples : 1 - Sum : 2 - Average : 2 - Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -array_get - Samples : 17950 - Sum : 23619 - Average : 1.3158217270194985 - Deviation: 0.2927357453775038 - Quartiles: [0, 1, 1, 2, 3] - -store_temp> - Samples : 17968 - Sum : 9565 - Average : 0.5323352626892253 - Deviation: 0.2566347513567351 - Quartiles: [0, 0, 1, 1, 2] - -unbox - Samples : 17176 - Sum : 30899 - Average : 1.7989636702375407 - Deviation: 0.39362025811193857 - Quartiles: [0, 1, 2, 2, 3] - -rename - Samples : 17968 - Sum : 9534 - Average : 0.5306099732858415 - Deviation: 0.25618680513651393 - Quartiles: [0, 0, 1, 1, 2] - -enable_ap_tracking - Samples : 11330 - Sum : 6114 - Average : 0.5396293027360989 - Deviation: 0.25478432860300737 - Quartiles: [0, 0, 1, 1, 2] - -dup - Samples : 80292 - Sum : 42478 - Average : 0.5290439894385492 - Deviation: 0.2539140813114104 - Quartiles: [0, 0, 1, 1, 2] - -u8_eq - Samples : 69089 - Sum : 38660 - Average : 0.5595680933288946 - Deviation: 0.25701772368834486 - Quartiles: [0, 0, 1, 1, 2] - -jump - Samples : 61087 - Sum : 32261 - Average : 0.5281156383518588 - Deviation: 0.2549717843584459 - Quartiles: [0, 0, 1, 1, 2] - -u32_to_felt252 - Samples : 2002 - Sum : 1137 - Average : 0.567932067932068 - Deviation: 0.2563742451354904 - Quartiles: [0, 0, 1, 1, 2] - -felt252_dict_entry_get - Samples : 1755 - Sum : 18119 - Average : 10.324216524216524 - Deviation: 3.628786779328069 - Quartiles: [7, 9, 10, 11, 16] - -felt252_dict_entry_finalize - Samples : 2002 - Sum : 1133 - Average : 0.5659340659340659 - Deviation: 0.26263571593240775 - Quartiles: [0, 0, 1, 1, 2] - -drop - Samples : 27167 - Sum : 14386 - Average : 0.5295395148525784 - Deviation: 0.2546488217076357 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 19292 - Sum : 10256 - Average : 0.5316193240721543 - Deviation: 0.25501307341473545 - Quartiles: [0, 0, 1, 1, 2] - -u32_overflowing_add - Samples : 17968 - Sum : 10513 - Average : 0.5850957257346393 - Deviation: 0.25689495967005 - Quartiles: [0, 0, 1, 1, 2] - -felt252_dict_squash - Samples : 2 - Sum : 709 - Average : 354.5 - Deviation: 112560.25 - Quartiles: [19, 19, 690, 690, 690] - -store_temp> - Samples : 2 - Sum : 2 - Average : 1 - Deviation: 1 - Quartiles: [0, 0, 2, 2, 2] - -alloc_local> - Samples : 17897 - Sum : 9454 - Average : 0.528244957255406 - Deviation: 0.25423099816210254 - Quartiles: [0, 0, 1, 1, 2] - -alloc_local - Samples : 17897 - Sum : 9462 - Average : 0.5286919595462927 - Deviation: 0.253758544938931 - Quartiles: [0, 0, 1, 1, 2] - -drop> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -drop>> - Samples : 16572 - Sum : 8730 - Average : 0.5267921795800145 - Deviation: 0.2539889133639719 - Quartiles: [0, 0, 1, 1, 2] - -struct_construct, Felt252Dict, u32, Unit>> - Samples : 1 - Sum : 0 - Average : 0 - Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -enum_init, core::dict::Felt252Dict::, core::integer::u32, ())>, 0> - Samples : 1 - Sum : 5 - Average : 5 - Deviation: 0 - Quartiles: [5, 5, 5, 5, 5] - -store_temp, core::dict::Felt252Dict::, core::integer::u32, ())>> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -store_local - Samples : 17896 - Sum : 9397 - Average : 0.5250894054537327 - Deviation: 0.2531702535176324 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 3315 - Sum : 1776 - Average : 0.5357466063348416 - Deviation: 0.25354872613856855 - Quartiles: [0, 0, 1, 1, 2] - -array_new - Samples : 13 - Sum : 8 - Average : 0.6153846153846154 - Deviation: 0.23668639053254445 - Quartiles: [0, 0, 1, 1, 1] - -array_append - Samples : 12 - Sum : 21 - Average : 1.75 - Deviation: 0.5208333333333334 - Quartiles: [1, 1, 2, 2, 3] - -u8_to_felt252 - Samples : 13 - Sum : 5 - Average : 0.38461538461538464 - Deviation: 0.23668639053254442 - Quartiles: [0, 0, 0, 1, 1] - -store_local> - Samples : 1324 - Sum : 694 - Average : 0.5241691842900302 - Deviation: 0.25545814660326177 - Quartiles: [0, 0, 1, 1, 2] - -dup - Samples : 20541 - Sum : 10881 - Average : 0.5297210457134511 - Deviation: 0.25310867540982385 - Quartiles: [0, 0, 1, 1, 2] - -felt252_dict_entry_get - Samples : 19046 - Sum : 207205 - Average : 10.879187230914628 - Deviation: 6.024100063968452 - Quartiles: [7, 9, 10, 12, 19] - -felt252_dict_entry_finalize - Samples : 20540 - Sum : 11574 - Average : 0.5634858812074002 - Deviation: 0.2570698350003962 - Quartiles: [0, 0, 1, 1, 2] - -u8_is_zero - Samples : 1990 - Sum : 1024 - Average : 0.5145728643216081 - Deviation: 0.2558177823792311 - Quartiles: [0, 0, 1, 1, 2] - -drop> - Samples : 1325 - Sum : 719 - Average : 0.5426415094339623 - Deviation: 0.25723830544677345 - Quartiles: [0, 0, 1, 1, 2] - -rename - Samples : 37133 - Sum : 19586 - Average : 0.5274553631540678 - Deviation: 0.2540397828685643 - Quartiles: [0, 0, 1, 1, 2] - -rename - Samples : 37132 - Sum : 19515 - Average : 0.5255574706452656 - Deviation: 0.25435597221676814 - Quartiles: [0, 0, 1, 1, 2] - -rename> - Samples : 37133 - Sum : 19697 - Average : 0.5304446179947755 - Deviation: 0.25343582148908145 - Quartiles: [0, 0, 1, 1, 2] - -rename> - Samples : 37133 - Sum : 19668 - Average : 0.5296636415048609 - Deviation: 0.2535904855218947 - Quartiles: [0, 0, 1, 1, 2] - -rename - Samples : 37133 - Sum : 19751 - Average : 0.5318988500794442 - Deviation: 0.2535606014077435 - Quartiles: [0, 0, 1, 1, 2] - -store_temp> - Samples : 13 - Sum : 5 - Average : 0.38461538461538464 - Deviation: 0.23668639053254442 - Quartiles: [0, 0, 0, 1, 1] - -print - Samples : 12 - Sum : 885 - Average : 73.75 - Deviation: 159.02083333333334 - Quartiles: [63, 64, 69, 88, 101] - -const_as_immediate> - Samples : 9268 - Sum : 4882 - Average : 0.5267587397496764 - Deviation: 0.2531683030365071 - Quartiles: [0, 0, 1, 1, 2] - -u8_overflowing_sub - Samples : 8602 - Sum : 4959 - Average : 0.5764938386421763 - Deviation: 0.2578664327102487 - Quartiles: [0, 0, 1, 1, 2] - -u8_overflowing_add - Samples : 667 - Sum : 383 - Average : 0.5742128935532234 - Deviation: 0.280474455425957 - Quartiles: [0, 0, 1, 1, 2] - -const_as_immediate> - Samples : 5299 - Sum : 2842 - Average : 0.5363276089828269 - Deviation: 0.25245460186278157 - Quartiles: [0, 0, 1, 1, 2] - -felt252_sub - Samples : 2648 - Sum : 1578 - Average : 0.5959214501510574 - Deviation: 0.26421297268188015 - Quartiles: [0, 0, 1, 1, 2] - -rename - Samples : 15245 - Sum : 8124 - Average : 0.5328960314857331 - Deviation: 0.2529847582951311 - Quartiles: [0, 0, 1, 1, 2] - -felt252_add - Samples : 2651 - Sum : 1574 - Average : 0.5937382119954734 - Deviation: 0.26007395485445434 - Quartiles: [0, 0, 1, 1, 2] - -felt252_dict_squash - Samples : 1 - Sum : 2 - Average : 2 - Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -store_temp> - Samples : 1 - Sum : 1 - Average : 1 - Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - From 34feaeb9e4cbedd7065f79fa26612660ff85a4ba Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Thu, 29 May 2025 18:49:59 -0300 Subject: [PATCH 05/27] fix clippy --- src/metadata/profiler.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index efd4913cd..8cdb45274 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -189,6 +189,7 @@ impl ProfilerMeta { Ok((value, core_idx)) } + #[allow(clippy::too_many_arguments)] /// Receives two timestamps, if they were originated in the same statement index /// the delta time between these two is calculated. If not, then the delta time is /// assigned to -1. Then it pushes the frame, which is made of the statement index From 5513c9986b71c8ddaddf73b742336ebe22d348cc Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Fri, 30 May 2025 11:28:17 -0300 Subject: [PATCH 06/27] add support for multiple profiles in a single execution --- src/bin/cairo-native-run.rs | 109 +++++-------------- src/metadata/profiler.rs | 203 +++++++++++++++++++++++++++++------- 2 files changed, 195 insertions(+), 117 deletions(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index e0af48f0e..b64b54019 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -136,6 +136,17 @@ fn main() -> anyhow::Result<()> { } } + #[cfg(feature = "with-libfunc-profiling")] + { + use cairo_native::metadata::profiler::ProfilerBinding; + + if let Some(trace_id) = executor.find_symbol_ptr(ProfilerBinding::TraceId.symbol()) + { + let trace_id = trace_id.cast::(); + unsafe { *trace_id = 0 }; + } + } + Box::new(move |function_id, args, gas, syscall_handler| { executor.invoke_dynamic_with_syscall_handler( function_id, @@ -158,6 +169,16 @@ fn main() -> anyhow::Result<()> { ); } + #[cfg(feature = "with-libfunc-profiling")] + { + use cairo_native::metadata::profiler::{ProfileImpl, LIBFUNC_PROFILE}; + + LIBFUNC_PROFILE + .lock() + .unwrap() + .insert(0, ProfileImpl::new(sierra_program.clone())); + } + let gas_metadata = GasMetadata::new(&sierra_program, Some(MetadataComputationConfig::default())).unwrap(); @@ -195,93 +216,19 @@ fn main() -> anyhow::Result<()> { #[cfg(feature = "with-libfunc-profiling")] { - use cairo_lang_sierra::{ids::ConcreteLibfuncId, program::Statement}; - use std::{collections::HashMap, fs::File, io::Write}; + use std::{fs::File, io::Write}; - let mut trace = HashMap::, u64)>::new(); - - for (statement_idx, tick_delta) in cairo_native::metadata::profiler::ProfilerImpl::take() { - if let Statement::Invocation(invocation) = &sierra_program.statements[statement_idx.0] { - let (tick_deltas, extra_count) = - trace.entry(invocation.libfunc_id.clone()).or_default(); - - if tick_delta != u64::MAX { - tick_deltas.push(tick_delta); - } else { - *extra_count += 1; - } - } - } - - let mut trace = trace - .into_iter() - .map(|(libfunc_id, (mut tick_deltas, extra_count))| { - tick_deltas.sort(); - - // Drop outliers. - { - let q1 = tick_deltas[tick_deltas.len() / 4]; - let q3 = tick_deltas[3 * tick_deltas.len() / 4]; - let iqr = q3 - q1; + let profile = cairo_native::metadata::profiler::LIBFUNC_PROFILE + .lock() + .unwrap(); - let q1_thr = q1.saturating_sub(iqr + iqr / 2); - let q3_thr = q3 + (iqr + iqr / 2); + assert_eq!(profile.values().len(), 1); - tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); - } - - // Compute the quartiles. - let quartiles = [ - *tick_deltas.first().unwrap(), - tick_deltas[tick_deltas.len() / 4], - tick_deltas[tick_deltas.len() / 2], - tick_deltas[3 * tick_deltas.len() / 4], - *tick_deltas.last().unwrap(), - ]; - - // Compuite the average. - let average = - tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; - - // Compute the standard deviation. - let std_dev = { - let sum = tick_deltas - .iter() - .copied() - .map(|x| x as f64) - .map(|x| (x - average)) - .map(|x| x * x) - .sum::(); - sum / (tick_deltas.len() as u64 + extra_count) as f64 - }; - - ( - libfunc_id, - ( - tick_deltas.len() as u64 + extra_count, - tick_deltas.iter().sum::() - + (extra_count as f64 * average).round() as u64, - quartiles, - average, - std_dev, - ), - ) - }) - .collect::>(); - - // Sort libfuncs by the order in which they are declared. - trace.sort_by_key(|(libfunc_id, _)| { - sierra_program - .libfunc_declarations - .iter() - .enumerate() - .find_map(|(i, x)| (&x.id == libfunc_id).then_some(i)) - .unwrap() - }); + let profile = profile.values().next().unwrap(); let mut output = File::create(args.profiler_output)?; - for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in trace { + for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in profile.process() { writeln!(output, "{libfunc_id}")?; writeln!(output, " Samples : {n_samples}")?; writeln!(output, " Sum : {sum}")?; diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 8cdb45274..2c75e512f 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -4,43 +4,50 @@ use crate::{ error::{Error, Result}, utils::BlockExt, }; -use cairo_lang_sierra::program::StatementIdx; +use cairo_lang_sierra::{ + ids::ConcreteLibfuncId, + program::{Program, Statement, StatementIdx}, +}; use melior::{ dialect::{ arith::{self, CmpiPredicate}, llvm::{self}, - ods, + memref, ods, }, ir::{ attribute::{FlatSymbolRefAttribute, StringAttribute, TypeAttribute}, operation::OperationBuilder, - r#type::IntegerType, + r#type::{IntegerType, MemRefType}, Attribute, Block, BlockLike, Identifier, Location, Module, Region, Value, }, Context, }; use std::{ - cell::{RefCell, UnsafeCell}, - collections::HashSet, + cell::RefCell, + collections::{HashMap, HashSet}, ffi::c_void, - mem, + ptr, + sync::{LazyLock, Mutex}, }; #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum ProfilerBinding { - CallBack, + PushStmt, + TraceId, } impl ProfilerBinding { pub const fn symbol(self) -> &'static str { match self { - ProfilerBinding::CallBack => "cairo_native__profiler__callback", + ProfilerBinding::PushStmt => "cairo_native__profiler__push_stmt", + ProfilerBinding::TraceId => "cairo_native__profiler__trace_id", } } const fn function_ptr(self) -> *const () { match self { - ProfilerBinding::CallBack => ProfilerImpl::callback as *const (), + ProfilerBinding::PushStmt => ProfileImpl::push_stmt as *const (), + ProfilerBinding::TraceId => ptr::null(), } } } @@ -71,9 +78,7 @@ impl ProfilerMeta { location: Location<'c>, binding: ProfilerBinding, ) -> Result> { - if !self.active_map.borrow().contains(&binding) { - self.active_map.borrow_mut().insert(binding); - + if self.active_map.borrow_mut().insert(binding) { module.body().append_operation( ods::llvm::mlir_global( context, @@ -106,6 +111,42 @@ impl ProfilerMeta { ) } + pub fn build_trace_id<'c, 'a>( + &self, + context: &'c Context, + module: &Module, + block: &'a Block<'c>, + location: Location<'c>, + ) -> Result> { + if self + .active_map + .borrow_mut() + .insert(ProfilerBinding::TraceId) + { + module.body().append_operation(memref::global( + context, + ProfilerBinding::TraceId.symbol(), + None, + MemRefType::new(IntegerType::new(context, 64).into(), &[], None, None), + None, + false, + None, + location, + )); + } + + let trace_id_ptr = block + .append_op_result(memref::get_global( + context, + ProfilerBinding::TraceId.symbol(), + MemRefType::new(IntegerType::new(context, 64).into(), &[], None, None), + location, + )) + .unwrap(); + + block.append_op_result(memref::load(trace_id_ptr, &[], location)) + } + /// Get the timestamp #[cfg(target_arch = "x86_64")] pub fn measure_timestamp<'c, 'a>( @@ -210,6 +251,8 @@ impl ProfilerMeta { // If core idx does not match: // Write statement idx and -1. + let trace_id = self.build_trace_id(context, module, block, location)?; + let i64_ty = IntegerType::new(context, 64).into(); let statement_idx = block.const_int_from_type(context, location, statement_idx, i64_ty)?; @@ -225,12 +268,12 @@ impl ProfilerMeta { ))?; let callback_ptr = - self.build_function(context, module, block, location, ProfilerBinding::CallBack)?; + self.build_function(context, module, block, location, ProfilerBinding::PushStmt)?; block.append_operation( ods::llvm::call( context, - &[callback_ptr, statement_idx, delta_value], + &[callback_ptr, trace_id, statement_idx, delta_value], location, ) .into(), @@ -239,43 +282,131 @@ impl ProfilerMeta { } } -thread_local! { - static PROFILER_IMPL: UnsafeCell = const { UnsafeCell::new(ProfilerImpl::new()) }; -} +pub static LIBFUNC_PROFILE: LazyLock>> = + LazyLock::new(|| Mutex::new(HashMap::new())); -pub struct ProfilerImpl { - trace: Vec<(StatementIdx, u64)>, +/// This represents a libfunc's profile, which has the following structure: +/// +/// `Vec<(libfunc_id, (samples_number, total_execution_time, quartiles, average_execution_time, standard_deviations))>`` +type ProfileInfo = Vec<(ConcreteLibfuncId, (u64, u64, [u64; 5], f64, f64))>; + +pub struct ProfileImpl { + pub trace: Vec<(StatementIdx, u64)>, + sierra_program: Program, } -impl ProfilerImpl { - const fn new() -> Self { - Self { trace: Vec::new() } +impl ProfileImpl { + pub fn new(sierra_program: Program) -> Self { + Self { + trace: Vec::new(), + sierra_program, + } } - pub fn take() -> Vec<(StatementIdx, u64)> { - PROFILER_IMPL.with(|x| { - let x = unsafe { &mut *x.get() }; + // Push a profiler frame + pub extern "C" fn push_stmt(trace_id: u64, statement_idx: u64, tick_delta: u64) { + let mut profiler = LIBFUNC_PROFILE.lock().unwrap(); - let mut trace = Vec::new(); - mem::swap(&mut x.trace, &mut trace); + let Some(profiler) = profiler.get_mut(&trace_id) else { + eprintln!("Could not find libfunc profiler!"); + return; + }; - trace - }) + profiler + .trace + .push((StatementIdx(statement_idx as usize), tick_delta)); } - // Push a profiler frame - pub extern "C" fn callback(statement_idx: u64, tick_delta: u64) { - PROFILER_IMPL.with(|x| { - let x = unsafe { &mut *x.get() }; + pub fn process(&self) -> ProfileInfo { + let mut trace = HashMap::, u64)>::new(); + + for (statement_idx, tick_delta) in self.trace.iter() { + if let Statement::Invocation(invocation) = + &self.sierra_program.statements[statement_idx.0] + { + let (tick_deltas, extra_count) = + trace.entry(invocation.libfunc_id.clone()).or_default(); + + if *tick_delta != u64::MAX { + tick_deltas.push(*tick_delta); + } else { + *extra_count += 1; + } + } + } - x.trace - .push((StatementIdx(statement_idx as usize), tick_delta)); + let mut trace = trace + .into_iter() + .map(|(libfunc_id, (mut tick_deltas, extra_count))| { + tick_deltas.sort(); + + // Drop outliers. + { + let q1 = tick_deltas[tick_deltas.len() / 4]; + let q3 = tick_deltas[3 * tick_deltas.len() / 4]; + let iqr = q3 - q1; + + let q1_thr = q1.saturating_sub(iqr + iqr / 2); + let q3_thr = q3 + (iqr + iqr / 2); + + tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); + } + + // Compute the quartiles. + let quartiles = [ + *tick_deltas.first().unwrap(), + tick_deltas[tick_deltas.len() / 4], + tick_deltas[tick_deltas.len() / 2], + tick_deltas[3 * tick_deltas.len() / 4], + *tick_deltas.last().unwrap(), + ]; + + // Compuite the average. + let average = + tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; + + // Compute the standard deviation. + let std_dev = { + let sum = tick_deltas + .iter() + .copied() + .map(|x| x as f64) + .map(|x| (x - average)) + .map(|x| x * x) + .sum::(); + sum / (tick_deltas.len() as u64 + extra_count) as f64 + }; + + ( + libfunc_id, + ( + tick_deltas.len() as u64 + extra_count, + tick_deltas.iter().sum::() + + (extra_count as f64 * average).round() as u64, + quartiles, + average, + std_dev, + ), + ) + }) + .collect::>(); + + // Sort libfuncs by the order in which they are declared. + trace.sort_by_key(|(libfunc_id, _)| { + self.sierra_program + .libfunc_declarations + .iter() + .enumerate() + .find_map(|(i, x)| (&x.id == libfunc_id).then_some(i)) + .unwrap() }); + + trace } } pub fn setup_runtime(find_symbol_ptr: impl Fn(&str) -> Option<*mut c_void>) { - let bindings = &[ProfilerBinding::CallBack]; + let bindings = &[ProfilerBinding::PushStmt]; for binding in bindings { if let Some(global) = find_symbol_ptr(binding.symbol()) { From c3faebfee092dc43c5dd7c8eec7c65aade5c9613 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Mon, 2 Jun 2025 15:28:52 -0300 Subject: [PATCH 07/27] better documentation --- Cargo.lock | 222 ++++++++++++++++++++++++--------------- Cargo.toml | 2 +- src/compiler.rs | 5 +- src/metadata/profiler.rs | 2 + 4 files changed, 142 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7a0220f8b..e434d95de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,12 +82,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] @@ -405,9 +405,9 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitvec" @@ -704,7 +704,7 @@ dependencies = [ "cairo-lang-sierra-to-casm", "cairo-lang-sierra-type-size", "cairo-lang-utils", - "cairo-vm 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-vm 2.2.0", "itertools 0.14.0", "thiserror", ] @@ -726,7 +726,7 @@ dependencies = [ "cairo-lang-sierra-to-casm", "cairo-lang-starknet", "cairo-lang-utils", - "cairo-vm 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-vm 2.2.0", "itertools 0.14.0", "keccak", "num-bigint", @@ -1087,12 +1087,16 @@ dependencies = [ [[package]] name = "cairo-vm" version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01805fcadbebfbfd1e176bc58e6b1be26362792bb008efe59aae9df0bba60a1" +source = "git+https://github.com/lambdaclass/cairo-vm?rev=368e3fb311601a33ff8945e784eaa332f1fd499a#368e3fb311601a33ff8945e784eaa332f1fd499a" dependencies = [ "anyhow", + "ark-ff 0.4.2", + "ark-std 0.4.0", "bincode 2.0.1", "bitvec", + "cairo-lang-casm", + "cairo-lang-starknet", + "cairo-lang-starknet-classes", "generic-array", "hashbrown 0.15.3", "hex", @@ -1112,14 +1116,14 @@ dependencies = [ "sha3", "starknet-crypto", "starknet-types-core", - "thiserror-no-std", + "thiserror", "zip", ] [[package]] name = "cairo-vm" version = "2.0.1" -source = "git+https://github.com/lambdaclass/cairo-vm?rev=368e3fb311601a33ff8945e784eaa332f1fd499a#368e3fb311601a33ff8945e784eaa332f1fd499a" +source = "git+https://github.com/lambdaclass/cairo-vm/?rev=3b36cd92f68f3dc26ddf5aba6c1f9a50ff3d303f#3b36cd92f68f3dc26ddf5aba6c1f9a50ff3d303f" dependencies = [ "anyhow", "ark-ff 0.4.2", @@ -1154,17 +1158,13 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "2.0.1" -source = "git+https://github.com/lambdaclass/cairo-vm/?rev=3b36cd92f68f3dc26ddf5aba6c1f9a50ff3d303f#3b36cd92f68f3dc26ddf5aba6c1f9a50ff3d303f" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a2f6d93aa279509d396d6f5c1992fa63d7d32c2b8d61ffa3398617c2cd0cd" dependencies = [ "anyhow", - "ark-ff 0.4.2", - "ark-std 0.4.0", "bincode 2.0.1", "bitvec", - "cairo-lang-casm", - "cairo-lang-starknet", - "cairo-lang-starknet-classes", "generic-array", "hashbrown 0.15.3", "hex", @@ -1228,9 +1228,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.21" +version = "1.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" +checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" dependencies = [ "shlex", ] @@ -1296,9 +1296,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" dependencies = [ "clap_builder", "clap_derive", @@ -1306,9 +1306,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" dependencies = [ "anstream", "anstyle", @@ -1739,9 +1739,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys 0.59.0", @@ -1886,9 +1886,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", @@ -2208,9 +2208,9 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.22.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7047a26de42016abf8f181b46b398aef0b77ad46711df41847f6ed869a2a1d5b" +checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" dependencies = [ "ascii-canvas", "bit-set", @@ -2230,9 +2230,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.22.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d05b3fe34b8bd562c338db725dfa9beb9451a48f65f129ccb9538b48d2c93b" +checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" dependencies = [ "regex-automata 0.4.9", "rustversion", @@ -2288,12 +2288,12 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.53.0", ] [[package]] @@ -2318,9 +2318,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -2352,9 +2352,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ "autocfg", "rawpointer", @@ -2554,6 +2554,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "oorandom" version = "11.1.5" @@ -2589,9 +2595,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.7.4" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9fde3d0718baf5bc92f577d652001da0f8d54cd03a7974e118d04fc888dc23d" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ "arrayvec", "bitvec", @@ -2605,9 +2611,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.7.4" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581c837bb6b9541ce7faa9377c20616e4fb7650f6b0f68bc93c827ee504fb7b3" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2617,9 +2623,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -2627,15 +2633,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2786,9 +2792,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", "syn 2.0.101", @@ -2945,7 +2951,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -3163,9 +3169,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "rusty-fork" @@ -3613,12 +3619,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.19.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", - "getrandom 0.3.2", + "getrandom 0.3.3", "once_cell", "rustix", "windows-sys 0.59.0", @@ -3687,26 +3693,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "thiserror-impl-no-std" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e6318948b519ba6dc2b442a6d0b904ebfb8d411a3ad3e07843615a72249758" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "thiserror-no-std" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ad459d94dd517257cc96add8a43190ee620011bb6e6cdc82dafd97dfafafea" -dependencies = [ - "thiserror-impl-no-std", -] - [[package]] name = "thread_local" version = "1.1.8" @@ -4154,7 +4140,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -4163,7 +4149,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -4172,14 +4158,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -4188,48 +4190,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.7.10" diff --git a/Cargo.toml b/Cargo.toml index 29fee6db4..099b13301 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ name = "starknet-native-compile" required-features = ["build-cli"] [features] -default = ["build-cli"] +default = ["with-libfunc-profiling", "build-cli"] build-cli = [ "dep:clap", "dep:tracing-subscriber", diff --git a/src/compiler.rs b/src/compiler.rs index 8958aac65..eec8587f1 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -616,8 +616,9 @@ fn compile_func( #[cfg(feature = "with-libfunc-profiling")] profiler: match libfunc { CoreConcreteLibfunc::FunctionCall(_) => { - // Tail-recursive function calls are broken. Also it'd include the entire function which - // doesn't make sense, therefore it's ignored on purpose. + // Tail-recursive function calls are broken beacuse a stack of timestamps is required, + // which would invalidate tail recursion. Also since each libfunc is measured individually, + // doesn't make sense to function calls into account, therefore it's ignored on purpose. None } _ => match metadata.remove::() diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 2c75e512f..2f706a7e0 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -327,6 +327,8 @@ impl ProfileImpl { let (tick_deltas, extra_count) = trace.entry(invocation.libfunc_id.clone()).or_default(); + // A tick_delta equal to u64::MAX implies it is invalid, so we don't take it + // into account if *tick_delta != u64::MAX { tick_deltas.push(*tick_delta); } else { From e809e70a370fb01a386d570870d435bc258ad074 Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Mon, 2 Jun 2025 15:31:37 -0300 Subject: [PATCH 08/27] typo Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> --- src/bin/cairo-native-run.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index f1b79ed9c..6f26f6099 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -48,7 +48,7 @@ struct Args { #[cfg(feature = "with-libfunc-profiling")] #[arg(long)] - /// The output path for the libfunc profilling results + /// The output path for the libfunc profiling results profiler_output: PathBuf, #[cfg(feature = "with-trace-dump")] From 9b20cd58721b90f9e7526fac0ecadae89a9b09d7 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Mon, 2 Jun 2025 15:47:44 -0300 Subject: [PATCH 09/27] make profiler_output optional --- src/bin/cairo-native-run.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index f1b79ed9c..fbdc7a58f 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -49,7 +49,7 @@ struct Args { #[cfg(feature = "with-libfunc-profiling")] #[arg(long)] /// The output path for the libfunc profilling results - profiler_output: PathBuf, + profiler_output: Option, #[cfg(feature = "with-trace-dump")] #[arg(long)] From ed51045d00338b4de3bc58e647ddb5f36ab49b3a Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Mon, 2 Jun 2025 16:55:19 -0300 Subject: [PATCH 10/27] clippy --- src/bin/cairo-native-run.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index fbdc7a58f..0de919c02 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -226,16 +226,18 @@ fn main() -> anyhow::Result<()> { let profile = profile.values().next().unwrap(); - let mut output = File::create(args.profiler_output)?; - - for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in profile.process() { - writeln!(output, "{libfunc_id}")?; - writeln!(output, " Samples : {n_samples}")?; - writeln!(output, " Sum : {sum}")?; - writeln!(output, " Average : {average}")?; - writeln!(output, " Deviation: {std_dev}")?; - writeln!(output, " Quartiles: {quartiles:?}")?; - writeln!(output)?; + if let Some(profiler_output_path) = args.profiler_output { + let mut output = File::create(profiler_output_path)?; + + for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in profile.process() { + writeln!(profile_file, "{libfunc_id}")?; + writeln!(profile_file, " Total Samples: {n_samples}")?; + writeln!(profile_file, " Total Execution Time: {sum}")?; + writeln!(profile_file, " Average Execution Time: {average}")?; + writeln!(profile_file, " Standard Deviation: {std_dev}")?; + writeln!(profile_file, " Quartiles: {quartiles:?}")?; + writeln!(profile_file)?; + } } } From ce831bde6cef3bd9dd1cbac58917c828f904146c Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Mon, 2 Jun 2025 17:04:36 -0300 Subject: [PATCH 11/27] clippy --- Cargo.lock | 4 ++-- src/bin/cairo-native-run.rs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e434d95de..d27e45295 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1190,9 +1190,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "0da45bc31171d8d6960122e222a67740df867c1dd53b4d51caa297084c185cab" dependencies = [ "serde", ] diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index 0de919c02..a0ccb1d0a 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -230,13 +230,13 @@ fn main() -> anyhow::Result<()> { let mut output = File::create(profiler_output_path)?; for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in profile.process() { - writeln!(profile_file, "{libfunc_id}")?; - writeln!(profile_file, " Total Samples: {n_samples}")?; - writeln!(profile_file, " Total Execution Time: {sum}")?; - writeln!(profile_file, " Average Execution Time: {average}")?; - writeln!(profile_file, " Standard Deviation: {std_dev}")?; - writeln!(profile_file, " Quartiles: {quartiles:?}")?; - writeln!(profile_file)?; + writeln!(output, "{libfunc_id}")?; + writeln!(output, " Total Samples: {n_samples}")?; + writeln!(output, " Total Execution Time: {sum}")?; + writeln!(output, " Average Execution Time: {average}")?; + writeln!(output, " Standard Deviation: {std_dev}")?; + writeln!(output, " Quartiles: {quartiles:?}")?; + writeln!(output)?; } } } From 95838ab9a38a94bc832cd345b4558360515af975 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Mon, 2 Jun 2025 17:11:02 -0300 Subject: [PATCH 12/27] change sequencer and replay's hash in blocks workflow --- .github/workflows/starknet-blocks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 5513f8b29..90669d052 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -32,7 +32,7 @@ jobs: with: repository: lambdaclass/starknet-replay path: starknet-replay - ref: 1b8e2e0be21a8df9f5f6b8f8514d1a40b456ef58 + ref: 2dc96309322d1c7a890b377a3f32340530ac672a # We need native to use the linux deps ci action - name: Checkout Native uses: actions/checkout@v4 @@ -43,7 +43,7 @@ jobs: with: repository: lambdaclass/sequencer path: sequencer - ref: 40331042c1149f5cb84b27f9dd8d47994a010bbe + ref: 09614fac7763f7e09f74efddf9a0ada7717ea85b - name: Cache RPC Calls uses: actions/cache@v4.2.0 From 6e0318913b8360b152f2837001044dd21426bedd Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Tue, 3 Jun 2025 11:25:50 -0300 Subject: [PATCH 13/27] forgot to remove libfunc-profilling from default features --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 099b13301..29fee6db4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ name = "starknet-native-compile" required-features = ["build-cli"] [features] -default = ["with-libfunc-profiling", "build-cli"] +default = ["build-cli"] build-cli = [ "dep:clap", "dep:tracing-subscriber", From 2ab1606b0f5762ad71685b13d57f89d606ec060e Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Mon, 9 Jun 2025 09:24:44 -0300 Subject: [PATCH 14/27] fix case with no deltas calculated --- src/metadata/profiler.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 2f706a7e0..cdf3a0b3d 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -340,6 +340,11 @@ impl ProfileImpl { let mut trace = trace .into_iter() .map(|(libfunc_id, (mut tick_deltas, extra_count))| { + // if no deltas were registered, we only return the libfunc's calls amount + if tick_deltas.is_empty() { + return (libfunc_id, (extra_count, 0, [0; 5], 0.0, 0.0)); + } + tick_deltas.sort(); // Drop outliers. From 714377adfb8598244efb21feff9271b766ec010d Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Mon, 9 Jun 2025 09:55:27 -0300 Subject: [PATCH 15/27] change sequencer and replay hashes in starknet-blocks workflow --- .github/workflows/starknet-blocks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index 90669d052..f477408e2 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -32,7 +32,7 @@ jobs: with: repository: lambdaclass/starknet-replay path: starknet-replay - ref: 2dc96309322d1c7a890b377a3f32340530ac672a + ref: 4c97cafd914709210ab7a7f728b7bf136b884be8 # We need native to use the linux deps ci action - name: Checkout Native uses: actions/checkout@v4 @@ -43,7 +43,7 @@ jobs: with: repository: lambdaclass/sequencer path: sequencer - ref: 09614fac7763f7e09f74efddf9a0ada7717ea85b + ref: 79e61eaea754f0728aeedd891527c495d51aca94 - name: Cache RPC Calls uses: actions/cache@v4.2.0 From 743cb0e445892448d9a21a7e61f90ec92bdc0775 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Tue, 10 Jun 2025 13:03:20 -0300 Subject: [PATCH 16/27] add information about return values for x86 --- src/metadata/profiler.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index cdf3a0b3d..f4e939db4 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -193,6 +193,13 @@ impl ProfilerMeta { let value = block.shli(value_hi, k32, location)?; let value = block.append_op_result(arith::ori(value, value_lo, location))?; + // Values + // 1. Timestamp + // 2. CPU's id core in which the program is running + // + // We use the last value to ensure that both the initial and then end timestamp of + // a libfunc's execution where calculated by the same core. This is to avoid gathering + // invalid data Ok((value, core_idx)) } From 6e99b28048cff9d32ccbba44efc64e757ac2f152 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Tue, 10 Jun 2025 18:06:26 -0300 Subject: [PATCH 17/27] reviews --- src/bin/cairo-native-run.rs | 91 ++++++++++++++++++++++--- src/compiler.rs | 2 +- src/libfuncs.rs | 1 + src/metadata/profiler.rs | 131 ++++++++++++++---------------------- 4 files changed, 134 insertions(+), 91 deletions(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index a0ccb1d0a..8963bf117 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -7,7 +7,7 @@ use cairo_lang_sierra_to_casm::metadata::MetadataComputationConfig; use cairo_native::{ context::NativeContext, executor::{AotNativeExecutor, JitNativeExecutor}, - metadata::gas::GasMetadata, + metadata::{gas::GasMetadata, profiler::LibfuncProfileSummary}, starknet_stub::StubSyscallHandler, }; use clap::{Parser, ValueEnum}; @@ -140,7 +140,8 @@ fn main() -> anyhow::Result<()> { { use cairo_native::metadata::profiler::ProfilerBinding; - if let Some(trace_id) = executor.find_symbol_ptr(ProfilerBinding::TraceId.symbol()) + if let Some(trace_id) = + executor.find_symbol_ptr(ProfilerBinding::ProfileId.symbol()) { let trace_id = trace_id.cast::(); unsafe { *trace_id = 0 }; @@ -216,6 +217,7 @@ fn main() -> anyhow::Result<()> { #[cfg(feature = "with-libfunc-profiling")] { + use cairo_native::metadata::profiler::LibfuncProfileSummary; use std::{fs::File, io::Write}; let profile = cairo_native::metadata::profiler::LIBFUNC_PROFILE @@ -229,12 +231,22 @@ fn main() -> anyhow::Result<()> { if let Some(profiler_output_path) = args.profiler_output { let mut output = File::create(profiler_output_path)?; - for (libfunc_id, (n_samples, sum, quartiles, average, std_dev)) in profile.process() { - writeln!(output, "{libfunc_id}")?; - writeln!(output, " Total Samples: {n_samples}")?; - writeln!(output, " Total Execution Time: {sum}")?; - writeln!(output, " Average Execution Time: {average}")?; - writeln!(output, " Standard Deviation: {std_dev}")?; + let profile = profile.process(|profile| process_profiles(profile)); + + for LibfuncProfileSummary { + libfunc_idx, + samples, + total_time, + average_time, + std_deviation, + quartiles, + } in profile.process() + { + writeln!(output, "{libfunc_idx}")?; + writeln!(output, " Total Samples: {samples}")?; + writeln!(output, " Total Execution Time: {total_time}")?; + writeln!(output, " Average Execution Time: {average_time}")?; + writeln!(output, " Standard Deviation: {std_deviation}")?; writeln!(output, " Quartiles: {quartiles:?}")?; writeln!(output)?; } @@ -258,3 +270,66 @@ fn main() -> anyhow::Result<()> { Ok(()) } + +fn process_profiles(profile: (ConcreteLibfuncId, (Vec, u64))) -> LibfuncProfileSummary { + let (libfunc_idx, (mut tick_deltas, extra_count)) = profile; + + // if no deltas were registered, we only return the libfunc's calls amount + if tick_deltas.is_empty() { + return ProfilerSummary { + libfunc_idx, + samples: extra_count, + total_time: 0, + average_time: 0.0, + std_deviation: 0.0, + quartiles: [0; 5], + }; + } + + tick_deltas.sort(); + + // Drop outliers. + { + let q1 = tick_deltas[tick_deltas.len() / 4]; + let q3 = tick_deltas[3 * tick_deltas.len() / 4]; + let iqr = q3 - q1; + + let q1_thr = q1.saturating_sub(iqr + iqr / 2); + let q3_thr = q3 + (iqr + iqr / 2); + + tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); + } + + // Compute the quartiles. + let quartiles = [ + *tick_deltas.first().unwrap(), + tick_deltas[tick_deltas.len() / 4], + tick_deltas[tick_deltas.len() / 2], + tick_deltas[3 * tick_deltas.len() / 4], + *tick_deltas.last().unwrap(), + ]; + + // Compuite the average. + let average = tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; + + // Compute the standard deviation. + let std_dev = { + let sum = tick_deltas + .iter() + .copied() + .map(|x| x as f64) + .map(|x| (x - average)) + .map(|x| x * x) + .sum::(); + sum / (tick_deltas.len() as u64 + extra_count) as f64 + }; + + LibfuncProfileSummary { + libfunc_idx, + samples: tick_deltas.len() as u64 + extra_count, + total_time: tick_deltas.iter().sum::() + (extra_count as f64 * average).round() as u64, + average_time: average, + std_deviation: std_dev, + quartiles, + } +} diff --git a/src/compiler.rs b/src/compiler.rs index 5f21fa0a5..539805efa 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -625,7 +625,7 @@ fn compile_func( CoreConcreteLibfunc::FunctionCall(_) => { // Tail-recursive function calls are broken beacuse a stack of timestamps is required, // which would invalidate tail recursion. Also since each libfunc is measured individually, - // doesn't make sense to function calls into account, therefore it's ignored on purpose. + // doesn't make sense to take function calls into account, therefore it's ignored on purpose. None } _ => match metadata.remove::() diff --git a/src/libfuncs.rs b/src/libfuncs.rs index 94d722531..b0718cf49 100644 --- a/src/libfuncs.rs +++ b/src/libfuncs.rs @@ -281,6 +281,7 @@ where pub results: Vec>>>>, #[cfg(feature = "with-libfunc-profiling")] + // Since function calls don't get profiled, this field is optional pub profiler: Option<( crate::metadata::profiler::ProfilerMeta, cairo_lang_sierra::program::StatementIdx, diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index f4e939db4..bdc4ae758 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -22,6 +22,8 @@ use melior::{ }, Context, }; +#[cfg(feature = "with-libfunc-profiling")] +use serde::Serialize; use std::{ cell::RefCell, collections::{HashMap, HashSet}, @@ -33,21 +35,21 @@ use std::{ #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum ProfilerBinding { PushStmt, - TraceId, + ProfileId, } impl ProfilerBinding { pub const fn symbol(self) -> &'static str { match self { ProfilerBinding::PushStmt => "cairo_native__profiler__push_stmt", - ProfilerBinding::TraceId => "cairo_native__profiler__trace_id", + ProfilerBinding::ProfileId => "cairo_native__profiler__profile_id", } } const fn function_ptr(self) -> *const () { match self { ProfilerBinding::PushStmt => ProfileImpl::push_stmt as *const (), - ProfilerBinding::TraceId => ptr::null(), + ProfilerBinding::ProfileId => ptr::null(), } } } @@ -111,7 +113,7 @@ impl ProfilerMeta { ) } - pub fn build_trace_id<'c, 'a>( + pub fn build_profile_id<'c, 'a>( &self, context: &'c Context, module: &Module, @@ -121,11 +123,11 @@ impl ProfilerMeta { if self .active_map .borrow_mut() - .insert(ProfilerBinding::TraceId) + .insert(ProfilerBinding::ProfileId) { module.body().append_operation(memref::global( context, - ProfilerBinding::TraceId.symbol(), + ProfilerBinding::ProfileId.symbol(), None, MemRefType::new(IntegerType::new(context, 64).into(), &[], None, None), None, @@ -135,19 +137,26 @@ impl ProfilerMeta { )); } - let trace_id_ptr = block + let trace_profile_ptr = block .append_op_result(memref::get_global( context, - ProfilerBinding::TraceId.symbol(), + ProfilerBinding::ProfileId.symbol(), MemRefType::new(IntegerType::new(context, 64).into(), &[], None, None), location, )) .unwrap(); - block.append_op_result(memref::load(trace_id_ptr, &[], location)) + block.append_op_result(memref::load(trace_profile_ptr, &[], location)) } /// Get the timestamp + /// Values + /// 1. Timestamp + /// 2. CPU's id core in which the program is running (only for x86 arch) + /// + /// We use the last value to ensure that both the initial and then end timestamp of + /// a libfunc's execution where calculated by the same core. This is to avoid gathering + /// invalid data #[cfg(target_arch = "x86_64")] pub fn measure_timestamp<'c, 'a>( &self, @@ -193,17 +202,17 @@ impl ProfilerMeta { let value = block.shli(value_hi, k32, location)?; let value = block.append_op_result(arith::ori(value, value_lo, location))?; - // Values - // 1. Timestamp - // 2. CPU's id core in which the program is running - // - // We use the last value to ensure that both the initial and then end timestamp of - // a libfunc's execution where calculated by the same core. This is to avoid gathering - // invalid data Ok((value, core_idx)) } /// Get the timestamp + /// Values + /// 1. Timestamp + /// 2. CPU's id core in which the program is running (only for x86 arch) + /// + /// We use the last value to ensure that both the initial and then end timestamp of + /// a libfunc's execution where calculated by the same core. This is to avoid gathering + /// invalid data #[cfg(target_arch = "aarch64")] pub fn measure_timestamp<'c, 'a>( &self, @@ -238,7 +247,7 @@ impl ProfilerMeta { } #[allow(clippy::too_many_arguments)] - /// Receives two timestamps, if they were originated in the same statement index + /// Receives two timestamps, if they were originated in the same CPU core, /// the delta time between these two is calculated. If not, then the delta time is /// assigned to -1. Then it pushes the frame, which is made of the statement index /// the delta time. @@ -248,6 +257,7 @@ impl ProfilerMeta { module: &Module, block: &Block<'c>, statement_idx: usize, + // (timestamp, core_idx) t0: (Value<'c, '_>, Value<'c, '_>), t1: (Value<'c, '_>, Value<'c, '_>), location: Location<'c>, @@ -258,7 +268,7 @@ impl ProfilerMeta { // If core idx does not match: // Write statement idx and -1. - let trace_id = self.build_trace_id(context, module, block, location)?; + let trace_id = self.build_profile_id(context, module, block, location)?; let i64_ty = IntegerType::new(context, 64).into(); @@ -285,6 +295,7 @@ impl ProfilerMeta { ) .into(), ); + Ok(()) } } @@ -292,10 +303,25 @@ impl ProfilerMeta { pub static LIBFUNC_PROFILE: LazyLock>> = LazyLock::new(|| Mutex::new(HashMap::new())); +/// `(libfunc_id, (vec, extra_count))` +/// +/// `extra_count`: a counter of libfunc calls whose execution time +/// hasn't been calculated for being invalid +type ProfileProcessor = dyn Fn((ConcreteLibfuncId, (Vec, u64))) -> LibfuncProfileSummary; + /// This represents a libfunc's profile, which has the following structure: /// /// `Vec<(libfunc_id, (samples_number, total_execution_time, quartiles, average_execution_time, standard_deviations))>`` -type ProfileInfo = Vec<(ConcreteLibfuncId, (u64, u64, [u64; 5], f64, f64))>; +#[cfg(feature = "with-libfunc-profiling")] +#[derive(Clone, Debug, Serialize)] +pub struct LibfuncProfileSummary { + pub libfunc_idx: ConcreteLibfuncId, + pub samples: u64, + pub total_time: u64, + pub average_time: f64, + pub std_deviation: f64, + pub quartiles: [u64; 5], +} pub struct ProfileImpl { pub trace: Vec<(StatementIdx, u64)>, @@ -324,7 +350,7 @@ impl ProfileImpl { .push((StatementIdx(statement_idx as usize), tick_delta)); } - pub fn process(&self) -> ProfileInfo { + pub fn process(&self, processor: ProfileProcessor) -> Vec { let mut trace = HashMap::, u64)>::new(); for (statement_idx, tick_delta) in self.trace.iter() { @@ -344,74 +370,15 @@ impl ProfileImpl { } } - let mut trace = trace - .into_iter() - .map(|(libfunc_id, (mut tick_deltas, extra_count))| { - // if no deltas were registered, we only return the libfunc's calls amount - if tick_deltas.is_empty() { - return (libfunc_id, (extra_count, 0, [0; 5], 0.0, 0.0)); - } - - tick_deltas.sort(); - - // Drop outliers. - { - let q1 = tick_deltas[tick_deltas.len() / 4]; - let q3 = tick_deltas[3 * tick_deltas.len() / 4]; - let iqr = q3 - q1; - - let q1_thr = q1.saturating_sub(iqr + iqr / 2); - let q3_thr = q3 + (iqr + iqr / 2); - - tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); - } - - // Compute the quartiles. - let quartiles = [ - *tick_deltas.first().unwrap(), - tick_deltas[tick_deltas.len() / 4], - tick_deltas[tick_deltas.len() / 2], - tick_deltas[3 * tick_deltas.len() / 4], - *tick_deltas.last().unwrap(), - ]; - - // Compuite the average. - let average = - tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; - - // Compute the standard deviation. - let std_dev = { - let sum = tick_deltas - .iter() - .copied() - .map(|x| x as f64) - .map(|x| (x - average)) - .map(|x| x * x) - .sum::(); - sum / (tick_deltas.len() as u64 + extra_count) as f64 - }; - - ( - libfunc_id, - ( - tick_deltas.len() as u64 + extra_count, - tick_deltas.iter().sum::() - + (extra_count as f64 * average).round() as u64, - quartiles, - average, - std_dev, - ), - ) - }) - .collect::>(); + let mut trace = trace.into_iter().map(processor).collect::>(); // Sort libfuncs by the order in which they are declared. - trace.sort_by_key(|(libfunc_id, _)| { + trace.sort_by_key(|ProfilerSummary { libfunc_idx, .. }| { self.sierra_program .libfunc_declarations .iter() .enumerate() - .find_map(|(i, x)| (&x.id == libfunc_id).then_some(i)) + .find_map(|(i, x)| (&x.id == libfunc_idx).then_some(i)) .unwrap() }); From 668ddf7d8a1860bd2430c14817ff9271fcdaf728 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Tue, 10 Jun 2025 19:27:41 -0300 Subject: [PATCH 18/27] clippy --- src/bin/cairo-native-run.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index 663faa776..f59e8371a 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -15,7 +15,10 @@ use std::path::PathBuf; use tracing_subscriber::{EnvFilter, FmtSubscriber}; use utils::{find_function, result_to_runresult}; #[cfg(feature = "with-trace-dump")] -use {cairo_lang_sierra::ids::ConcreteLibfuncId, profiler::LibfuncProfileSummary}; +use { + cairo_lang_sierra::ids::ConcreteLibfuncId, + cairo_native::metadata::profiler::LibfuncProfileSummary, +}; mod utils; From 69d90afb838c6c2c0395701d4020135cb879d619 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Wed, 11 Jun 2025 10:42:20 -0300 Subject: [PATCH 19/27] add documentation and change summarize_profiles to return a generic --- src/bin/cairo-native-run.rs | 12 +++++++- src/context.rs | 2 +- src/metadata/profiler.rs | 60 +++++++++++++++++++++++-------------- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index f59e8371a..639254adf 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -236,7 +236,17 @@ fn main() -> anyhow::Result<()> { if let Some(profiler_output_path) = args.profiler_output { let mut output = File::create(profiler_output_path)?; - let processed_profile = profile.process(process_profiles); + let mut processed_profile = profile.summarize_profiles(process_profiles); + + processed_profile.sort_by_key(|LibfuncProfileSummary { libfunc_idx, .. }| { + profile + .sierra_program() + .libfunc_declarations + .iter() + .enumerate() + .find_map(|(i, x)| (x.id == *libfunc_idx).then_some(i)) + .unwrap() + }); for LibfuncProfileSummary { libfunc_idx, diff --git a/src/context.rs b/src/context.rs index 3e167a58c..a6167780f 100644 --- a/src/context.rs +++ b/src/context.rs @@ -164,7 +164,7 @@ impl NativeContext { metadata.insert(gas_metadata); #[cfg(feature = "with-libfunc-profiling")] - metadata.insert(crate::metadata::profiler::ProfilerMeta::new()?); + metadata.insert(crate::metadata::profiler::ProfilerMeta::new()); // Create the Sierra program registry let registry = ProgramRegistry::::new(program)?; diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 2fabc7d74..a2b42c8df 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -1,4 +1,26 @@ #![cfg(feature = "with-libfunc-profiling")] +//! The libfunc profiling feature is used to generate information about every libfunc executed in a sierra program. +//! +//! When this feature is used, the compiler will call the important methods: +//! 1. `measure_timestamp`: called before every libfunc execution. +//! +//! 2. `push_frame`: called before every branching operation. This method will also call `measure_timestamp`. This, +//! with the timestamp calculated before the execution, will allow to measure each libfunc's execution time. Apart +//! from that, it will count every libfunc's call, allowing to summarize every libfun'c execution execution time. +//! +//! Once the program execution finished and the information was gathered, a `summarize_profiles` can be called. It +//! exepects a closure to process this information. +//! +//! As well as with the trace-dump fature, in the context of starknet contracts, we need to add support for building +//! profiles for multiple programs. To do so, we need two important elements, which must be set before every contract +//! execution: +//! +//! 1. A glbal static hashmap to map every profile id to its respective profile summary. See `LIBFUNC_PROFILE`. +//! +//! 2. A counter to track the ID of the current libfunc profile, which gets updated every time we switch to another +//! contract. Since a contract can call other contract's, we need a way of restoring the counter after every execution. +//! +//! See cairo-native-run` for an example on how to do it. use crate::{ error::{Error, Result}, @@ -54,18 +76,16 @@ impl ProfilerBinding { } } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct ProfilerMeta { active_map: RefCell>, - _private: (), } impl ProfilerMeta { - pub fn new() -> Result { - Ok(Self { + pub fn new() -> Self { + Self { active_map: RefCell::new(HashSet::new()), - _private: (), - }) + } } /// Register the global for the given binding, if not yet registered, and return @@ -330,6 +350,10 @@ impl ProfileImpl { } } + pub fn sierra_program(&self) -> &Program { + &self.sierra_program + } + // Push a profiler frame pub extern "C" fn push_stmt(trace_id: u64, statement_idx: u64, tick_delta: u64) { let mut profiler = LIBFUNC_PROFILE.lock().unwrap(); @@ -346,13 +370,15 @@ impl ProfileImpl { /// Process profiling results. /// - /// Receives a closure with the flowing paramaters `(libfunc_id, (vec, extra_count))` + /// Receives a closure with the flowing paramaters `(libfunc_id, (vec, extra_count))` to + /// process profiles information. /// /// `extra_count`: counter of libfunc calls whose execution time - /// hasn't been calculated for being invalid - pub fn process(&self, processor: F) -> Vec + /// hasn't been calculated for being invalid. + /// + pub fn summarize_profiles(&self, processor: F) -> Vec where - F: FnMut((ConcreteLibfuncId, (Vec, u64))) -> LibfuncProfileSummary, + F: FnMut((ConcreteLibfuncId, (Vec, u64))) -> R, { let mut trace = HashMap::, u64)>::new(); @@ -373,19 +399,7 @@ impl ProfileImpl { } } - let mut trace = trace.into_iter().map(processor).collect::>(); - - // Sort libfuncs by the order in which they are declared. - trace.sort_by_key(|LibfuncProfileSummary { libfunc_idx, .. }| { - self.sierra_program - .libfunc_declarations - .iter() - .enumerate() - .find_map(|(i, x)| (x.id == *libfunc_idx).then_some(i)) - .unwrap() - }); - - trace + trace.into_iter().map(processor).collect::>() } } From be18409c93a0d16af73cee3f844ad9933c526be5 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Wed, 11 Jun 2025 10:45:31 -0300 Subject: [PATCH 20/27] move LibfuncSummary to cairo-native-run --- src/bin/cairo-native-run.rs | 14 ++++++++++++++ src/metadata/profiler.rs | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index 639254adf..292233ca3 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -286,6 +286,20 @@ fn main() -> anyhow::Result<()> { Ok(()) } +/// This represents a libfunc's profile, which has the following structure: +/// +/// `Vec<(libfunc_id, (samples_number, total_execution_time, quartiles, average_execution_time, standard_deviations))>`` +#[cfg(feature = "with-libfunc-profiling")] +#[derive(Clone, Debug, Serialize)] +pub struct LibfuncProfileSummary { + pub libfunc_idx: ConcreteLibfuncId, + pub samples: u64, + pub total_time: u64, + pub average_time: f64, + pub std_deviation: f64, + pub quartiles: [u64; 5], +} + #[cfg(feature = "with-trace-dump")] fn process_profiles(profile: (ConcreteLibfuncId, (Vec, u64))) -> LibfuncProfileSummary { let (libfunc_idx, (mut tick_deltas, extra_count)) = profile; diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index a2b42c8df..0a4a5dec7 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -323,20 +323,6 @@ impl ProfilerMeta { pub static LIBFUNC_PROFILE: LazyLock>> = LazyLock::new(|| Mutex::new(HashMap::new())); -/// This represents a libfunc's profile, which has the following structure: -/// -/// `Vec<(libfunc_id, (samples_number, total_execution_time, quartiles, average_execution_time, standard_deviations))>`` -#[cfg(feature = "with-libfunc-profiling")] -#[derive(Clone, Debug, Serialize)] -pub struct LibfuncProfileSummary { - pub libfunc_idx: ConcreteLibfuncId, - pub samples: u64, - pub total_time: u64, - pub average_time: f64, - pub std_deviation: f64, - pub quartiles: [u64; 5], -} - pub struct ProfileImpl { pub trace: Vec<(StatementIdx, u64)>, sierra_program: Program, From 44de79b56a342b9ec9d5f866c12b3c58bd084610 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Wed, 11 Jun 2025 10:49:41 -0300 Subject: [PATCH 21/27] move LibfuncSummary to cairo-native-run --- src/bin/cairo-native-run.rs | 9 ++------- src/metadata/profiler.rs | 1 - 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index 292233ca3..e947278f3 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -3,6 +3,8 @@ use cairo_lang_compiler::{ compile_prepared_db, db::RootDatabase, project::setup_project, CompilerConfig, }; use cairo_lang_runner::short_string::as_cairo_short_string; +#[cfg(feature = "with-trace-dump")] +use cairo_lang_sierra::ids::ConcreteLibfuncId; use cairo_lang_sierra_to_casm::metadata::MetadataComputationConfig; use cairo_native::{ context::NativeContext, @@ -14,11 +16,6 @@ use clap::{Parser, ValueEnum}; use std::path::PathBuf; use tracing_subscriber::{EnvFilter, FmtSubscriber}; use utils::{find_function, result_to_runresult}; -#[cfg(feature = "with-trace-dump")] -use { - cairo_lang_sierra::ids::ConcreteLibfuncId, - cairo_native::metadata::profiler::LibfuncProfileSummary, -}; mod utils; @@ -222,7 +219,6 @@ fn main() -> anyhow::Result<()> { #[cfg(feature = "with-libfunc-profiling")] { - use cairo_native::metadata::profiler::LibfuncProfileSummary; use std::{fs::File, io::Write}; let profile = cairo_native::metadata::profiler::LIBFUNC_PROFILE @@ -290,7 +286,6 @@ fn main() -> anyhow::Result<()> { /// /// `Vec<(libfunc_id, (samples_number, total_execution_time, quartiles, average_execution_time, standard_deviations))>`` #[cfg(feature = "with-libfunc-profiling")] -#[derive(Clone, Debug, Serialize)] pub struct LibfuncProfileSummary { pub libfunc_idx: ConcreteLibfuncId, pub samples: u64, diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 0a4a5dec7..241d07d5d 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -45,7 +45,6 @@ use melior::{ Context, }; #[cfg(feature = "with-libfunc-profiling")] -use serde::Serialize; use std::{ cell::RefCell, collections::{HashMap, HashSet}, From 19960d3bdb51cff89976d462446d0e9e16ddbb67 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Thu, 12 Jun 2025 15:27:52 -0300 Subject: [PATCH 22/27] remove closure and return raw data --- .github/workflows/starknet-blocks.yml | 5 +- profile.md | 784 ++++++++++++++++++++++++++ src/bin/cairo-native-run.rs | 140 ++--- src/metadata/profiler.rs | 31 +- 4 files changed, 871 insertions(+), 89 deletions(-) create mode 100644 profile.md diff --git a/.github/workflows/starknet-blocks.yml b/.github/workflows/starknet-blocks.yml index f477408e2..b89f5bd53 100644 --- a/.github/workflows/starknet-blocks.yml +++ b/.github/workflows/starknet-blocks.yml @@ -32,7 +32,7 @@ jobs: with: repository: lambdaclass/starknet-replay path: starknet-replay - ref: 4c97cafd914709210ab7a7f728b7bf136b884be8 + ref: d36491aa5fca3f48b4d7fb25eba599603ff48225 # We need native to use the linux deps ci action - name: Checkout Native uses: actions/checkout@v4 @@ -43,8 +43,7 @@ jobs: with: repository: lambdaclass/sequencer path: sequencer - ref: 79e61eaea754f0728aeedd891527c495d51aca94 - + ref: 14be65ca995ac702bad26ac20f2a522d9515f70a - name: Cache RPC Calls uses: actions/cache@v4.2.0 with: diff --git a/profile.md b/profile.md new file mode 100644 index 000000000..4a3414394 --- /dev/null +++ b/profile.md @@ -0,0 +1,784 @@ +alloc_local> + Total Samples: 17970 + Total Execution Time: 7543 + Average Execution Time: 0.41975514746800224 + Standard Deviation: 0.2435607636421274 + Quartiles: [0, 0, 0, 1, 1] + +finalize_locals + Total Samples: 17969 + Total Execution Time: 7683 + Average Execution Time: 0.42756970337803996 + Standard Deviation: 0.24475385213129322 + Quartiles: [0, 0, 0, 1, 1] + +disable_ap_tracking + Total Samples: 29305 + Total Execution Time: 12420 + Average Execution Time: 0.4238184610134789 + Standard Deviation: 0.24433286859624354 + Quartiles: [0, 0, 0, 1, 2] + +felt252_dict_new + Total Samples: 2 + Total Execution Time: 6 + Average Execution Time: 3 + Standard Deviation: 0 + Quartiles: [3, 3, 3, 3, 3] + +const_as_immediate> + Total Samples: 3 + Total Execution Time: 3 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +store_temp + Total Samples: 75707 + Total Execution Time: 31709 + Average Execution Time: 0.4188384165268733 + Standard Deviation: 0.24367697373231473 + Quartiles: [0, 0, 0, 1, 2] + +store_temp + Total Samples: 17977 + Total Execution Time: 7561 + Average Execution Time: 0.42059297991878514 + Standard Deviation: 0.2444732980382943 + Quartiles: [0, 0, 0, 1, 2] + +store_temp + Total Samples: 59872 + Total Execution Time: 25452 + Average Execution Time: 0.42510689470871194 + Standard Deviation: 0.24469166414817833 + Quartiles: [0, 0, 0, 1, 2] + +store_temp + Total Samples: 89921 + Total Execution Time: 38120 + Average Execution Time: 0.4239276698435293 + Standard Deviation: 0.24443541804007066 + Quartiles: [0, 0, 0, 1, 2] + +store_temp>> + Total Samples: 17970 + Total Execution Time: 7598 + Average Execution Time: 0.4228158041179744 + Standard Deviation: 0.24437648972239143 + Quartiles: [0, 0, 0, 1, 2] + +store_temp> + Total Samples: 50810 + Total Execution Time: 21632 + Average Execution Time: 0.42574296398346784 + Standard Deviation: 0.24464334192323936 + Quartiles: [0, 0, 0, 1, 2] + +enum_match, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>> + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +branch_align + Total Samples: 153552 + Total Execution Time: 64758 + Average Execution Time: 0.42173335417317914 + Standard Deviation: 0.24421297964471228 + Quartiles: [0, 0, 0, 1, 2] + +redeposit_gas + Total Samples: 32021 + Total Execution Time: 32021 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +struct_deconstruct, u32, Felt252Dict, u32, Unit>> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +drop + Total Samples: 17981 + Total Execution Time: 7587 + Average Execution Time: 0.4219453867971748 + Standard Deviation: 0.24412993439568562 + Quartiles: [0, 0, 0, 1, 2] + +drop + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +store_local> + Total Samples: 17966 + Total Execution Time: 7590 + Average Execution Time: 0.4224646554603139 + Standard Deviation: 0.24432223450166501 + Quartiles: [0, 0, 0, 1, 2] + +drop> + Total Samples: 2 + Total Execution Time: 90 + Average Execution Time: 45 + Standard Deviation: 576 + Quartiles: [21, 21, 69, 69, 69] + +drop>> + Total Samples: 2 + Total Execution Time: 2 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +alloc_local>> + Total Samples: 53838 + Total Execution Time: 22820 + Average Execution Time: 0.4238641851480367 + Standard Deviation: 0.24442622859166338 + Quartiles: [0, 0, 0, 1, 2] + +alloc_local> + Total Samples: 2 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +felt252_dict_new + Total Samples: 1 + Total Execution Time: 17 + Average Execution Time: 17 + Standard Deviation: 0 + Quartiles: [17, 17, 17, 17, 17] + +dup>> + Total Samples: 35928 + Total Execution Time: 18903 + Average Execution Time: 0.5261356045424181 + Standard Deviation: 0.2517106064167782 + Quartiles: [0, 0, 1, 1, 2] + +store_local> + Total Samples: 2 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +drop>>> + Total Samples: 53837 + Total Execution Time: 22624 + Average Execution Time: 0.4202314393446886 + Standard Deviation: 0.24411991597371122 + Quartiles: [0, 0, 0, 1, 2] + +const_as_immediate> + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +store_temp + Total Samples: 35793 + Total Execution Time: 15108 + Average Execution Time: 0.4220937054731372 + Standard Deviation: 0.2443776240524776 + Quartiles: [0, 0, 0, 1, 2] + +store_temp> + Total Samples: 59650 + Total Execution Time: 25189 + Average Execution Time: 0.4222799664710813 + Standard Deviation: 0.24412724098178706 + Quartiles: [0, 0, 0, 1, 2] + +store_temp>> + Total Samples: 17897 + Total Execution Time: 7623 + Average Execution Time: 0.42593730792870316 + Standard Deviation: 0.2449617199341363 + Quartiles: [0, 0, 0, 1, 2] + +enum_match, core::dict::Felt252Dict::, core::integer::u32, ())>> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +struct_deconstruct, Felt252Dict, u32, Unit>> + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +drop + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +drop> + Total Samples: 1 + Total Execution Time: 18 + Average Execution Time: 18 + Standard Deviation: 0 + Quartiles: [18, 18, 18, 18, 18] + +struct_construct> + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +enum_init, 0> + Total Samples: 1 + Total Execution Time: 2 + Average Execution Time: 2 + Standard Deviation: 0 + Quartiles: [2, 2, 2, 2, 2] + +store_temp> + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +drop>> + Total Samples: 1 + Total Execution Time: 6 + Average Execution Time: 6 + Standard Deviation: 0 + Quartiles: [6, 6, 6, 6, 6] + +drop>> + Total Samples: 2 + Total Execution Time: 19 + Average Execution Time: 9.5 + Standard Deviation: 72.25 + Quartiles: [1, 1, 18, 18, 18] + +alloc_local> + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +array_new + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +const_as_immediate> + Total Samples: 12607 + Total Execution Time: 5308 + Average Execution Time: 0.4210359324184977 + Standard Deviation: 0.2437646760309274 + Quartiles: [0, 0, 0, 1, 1] + +store_temp + Total Samples: 29953 + Total Execution Time: 12634 + Average Execution Time: 0.4217941441591827 + Standard Deviation: 0.24401738666220757 + Quartiles: [0, 0, 0, 1, 2] + +array_append + Total Samples: 70 + Total Execution Time: 27 + Average Execution Time: 0.38571428571428573 + Standard Deviation: 0.2655102040816325 + Quartiles: [0, 0, 0, 1, 2] + +const_as_immediate> + Total Samples: 3390 + Total Execution Time: 1469 + Average Execution Time: 0.43333333333333335 + Standard Deviation: 0.24614552605703674 + Quartiles: [0, 0, 0, 1, 2] + +const_as_immediate> + Total Samples: 11950 + Total Execution Time: 5134 + Average Execution Time: 0.4296234309623431 + Standard Deviation: 0.24521450254726676 + Quartiles: [0, 0, 0, 1, 2] + +const_as_immediate> + Total Samples: 17911 + Total Execution Time: 7593 + Average Execution Time: 0.4239294288426107 + Standard Deviation: 0.24432493142757067 + Quartiles: [0, 0, 0, 1, 2] + +const_as_immediate> + Total Samples: 15254 + Total Execution Time: 6333 + Average Execution Time: 0.4151697915300905 + Standard Deviation: 0.24293494888160955 + Quartiles: [0, 0, 0, 1, 2] + +const_as_immediate> + Total Samples: 1397 + Total Execution Time: 572 + Average Execution Time: 0.4094488188976378 + Standard Deviation: 0.24180048360096582 + Quartiles: [0, 0, 0, 1, 1] + +const_as_immediate> + Total Samples: 3338 + Total Execution Time: 1430 + Average Execution Time: 0.4284002396644697 + Standard Deviation: 0.2454726354942492 + Quartiles: [0, 0, 0, 1, 2] + +store_local> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +snapshot_take> + Total Samples: 1 + Total Execution Time: 48 + Average Execution Time: 48 + Standard Deviation: 0 + Quartiles: [48, 48, 48, 48, 48] + +drop> + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +struct_construct + Total Samples: 3 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +enum_init>, 1> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +withdraw_gas + Total Samples: 15796 + Total Execution Time: 15796 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +array_len + Total Samples: 17970 + Total Execution Time: 10129 + Average Execution Time: 0.5636616583194213 + Standard Deviation: 0.24639237968183855 + Quartiles: [0, 0, 1, 1, 2] + +dup + Total Samples: 37948 + Total Execution Time: 16114 + Average Execution Time: 0.4246337092863919 + Standard Deviation: 0.2447942555222798 + Quartiles: [0, 0, 0, 1, 2] + +u32_overflowing_sub + Total Samples: 19295 + Total Execution Time: 8898 + Average Execution Time: 0.46115573982897123 + Standard Deviation: 0.24911304622966463 + Quartiles: [0, 0, 0, 1, 2] + +struct_construct, u32, Felt252Dict, u32, Unit>> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +enum_init, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>, 0> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +store_temp, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +array_get + Total Samples: 17279 + Total Execution Time: 17279 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +store_temp> + Total Samples: 17967 + Total Execution Time: 7612 + Average Execution Time: 0.42366560917237156 + Standard Deviation: 0.24461832153274635 + Quartiles: [0, 0, 0, 1, 2] + +unbox + Total Samples: 17130 + Total Execution Time: 17130 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +rename + Total Samples: 17968 + Total Execution Time: 7770 + Average Execution Time: 0.43243544078361534 + Standard Deviation: 0.24554633933171735 + Quartiles: [0, 0, 0, 1, 2] + +enable_ap_tracking + Total Samples: 11331 + Total Execution Time: 4734 + Average Execution Time: 0.4177918983320095 + Standard Deviation: 0.24341833494801057 + Quartiles: [0, 0, 0, 1, 2] + +dup + Total Samples: 80294 + Total Execution Time: 33952 + Average Execution Time: 0.4228460408000598 + Standard Deviation: 0.24444580196201987 + Quartiles: [0, 0, 0, 1, 2] + +u8_eq + Total Samples: 69091 + Total Execution Time: 29231 + Average Execution Time: 0.42307970647407045 + Standard Deviation: 0.24440168907756138 + Quartiles: [0, 0, 0, 1, 2] + +jump + Total Samples: 61088 + Total Execution Time: 25716 + Average Execution Time: 0.4209664745940283 + Standard Deviation: 0.24404835875042852 + Quartiles: [0, 0, 0, 1, 2] + +u32_to_felt252 + Total Samples: 2002 + Total Execution Time: 906 + Average Execution Time: 0.45254745254745254 + Standard Deviation: 0.2477482557402536 + Quartiles: [0, 0, 0, 1, 1] + +felt252_dict_entry_get + Total Samples: 1984 + Total Execution Time: 18861 + Average Execution Time: 9.506552419354838 + Standard Deviation: 0.30741674321995127 + Quartiles: [8, 9, 9, 10, 11] + +felt252_dict_entry_finalize + Total Samples: 2002 + Total Execution Time: 928 + Average Execution Time: 0.46353646353646355 + Standard Deviation: 0.2486704105085778 + Quartiles: [0, 0, 0, 1, 1] + +drop + Total Samples: 27168 + Total Execution Time: 11416 + Average Execution Time: 0.4202002355712603 + Standard Deviation: 0.24422092574794188 + Quartiles: [0, 0, 0, 1, 2] + +const_as_immediate> + Total Samples: 19293 + Total Execution Time: 8115 + Average Execution Time: 0.42061887731301506 + Standard Deviation: 0.2439059664440165 + Quartiles: [0, 0, 0, 1, 2] + +u32_overflowing_add + Total Samples: 17968 + Total Execution Time: 8251 + Average Execution Time: 0.4592052537845058 + Standard Deviation: 0.24866971566244478 + Quartiles: [0, 0, 0, 1, 2] + +felt252_dict_squash + Total Samples: 2 + Total Execution Time: 51 + Average Execution Time: 25.5 + Standard Deviation: 56.25 + Quartiles: [18, 18, 33, 33, 33] + +store_temp> + Total Samples: 2 + Total Execution Time: 1 + Average Execution Time: 0.5 + Standard Deviation: 0.25 + Quartiles: [0, 0, 1, 1, 1] + +alloc_local> + Total Samples: 17897 + Total Execution Time: 7587 + Average Execution Time: 0.4239257976197128 + Standard Deviation: 0.2443244663048958 + Quartiles: [0, 0, 0, 1, 2] + +alloc_local + Total Samples: 17896 + Total Execution Time: 7570 + Average Execution Time: 0.42299955297273134 + Standard Deviation: 0.24485322887778174 + Quartiles: [0, 0, 0, 1, 2] + +drop> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +drop>> + Total Samples: 16572 + Total Execution Time: 6905 + Average Execution Time: 0.4166666666666667 + Standard Deviation: 0.24341761203637532 + Quartiles: [0, 0, 0, 1, 2] + +struct_construct, Felt252Dict, u32, Unit>> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +enum_init, core::dict::Felt252Dict::, core::integer::u32, ())>, 0> + Total Samples: 1 + Total Execution Time: 5 + Average Execution Time: 5 + Standard Deviation: 0 + Quartiles: [5, 5, 5, 5, 5] + +store_temp, core::dict::Felt252Dict::, core::integer::u32, ())>> + Total Samples: 1 + Total Execution Time: 0 + Average Execution Time: 0 + Standard Deviation: 0 + Quartiles: [0, 0, 0, 0, 0] + +store_local + Total Samples: 17896 + Total Execution Time: 7659 + Average Execution Time: 0.4279727313366115 + Standard Deviation: 0.24537085665477268 + Quartiles: [0, 0, 0, 1, 2] + +const_as_immediate> + Total Samples: 3315 + Total Execution Time: 1365 + Average Execution Time: 0.4117647058823529 + Standard Deviation: 0.24221453287196662 + Quartiles: [0, 0, 0, 1, 1] + +array_new + Total Samples: 13 + Total Execution Time: 4 + Average Execution Time: 0.3076923076923077 + Standard Deviation: 0.21301775147928995 + Quartiles: [0, 0, 0, 1, 1] + +array_append + Total Samples: 12 + Total Execution Time: 20 + Average Execution Time: 1.6666666666666667 + Standard Deviation: 0.2222222222222223 + Quartiles: [1, 1, 2, 2, 2] + +u8_to_felt252 + Total Samples: 13 + Total Execution Time: 7 + Average Execution Time: 0.5384615384615384 + Standard Deviation: 0.24852071005917167 + Quartiles: [0, 0, 1, 1, 1] + +store_local> + Total Samples: 1325 + Total Execution Time: 597 + Average Execution Time: 0.4505660377358491 + Standard Deviation: 0.24755628337487107 + Quartiles: [0, 0, 0, 1, 1] + +dup + Total Samples: 20540 + Total Execution Time: 8611 + Average Execution Time: 0.41923076923076924 + Standard Deviation: 0.2437684443112503 + Quartiles: [0, 0, 0, 1, 2] + +felt252_dict_entry_get + Total Samples: 20467 + Total Execution Time: 192907 + Average Execution Time: 9.425269946743539 + Standard Deviation: 0.2973787259267783 + Quartiles: [8, 9, 9, 10, 11] + +felt252_dict_entry_finalize + Total Samples: 20541 + Total Execution Time: 9201 + Average Execution Time: 0.4479334014897035 + Standard Deviation: 0.24767853429206335 + Quartiles: [0, 0, 0, 1, 2] + +u8_is_zero + Total Samples: 1990 + Total Execution Time: 862 + Average Execution Time: 0.43316582914572865 + Standard Deviation: 0.2455331936062132 + Quartiles: [0, 0, 0, 1, 1] + +drop> + Total Samples: 1325 + Total Execution Time: 553 + Average Execution Time: 0.41735849056603774 + Standard Deviation: 0.24317038091847656 + Quartiles: [0, 0, 0, 1, 1] + +rename + Total Samples: 37133 + Total Execution Time: 15645 + Average Execution Time: 0.42132335119704845 + Standard Deviation: 0.24391770582824324 + Quartiles: [0, 0, 0, 1, 2] + +rename + Total Samples: 37133 + Total Execution Time: 15653 + Average Execution Time: 0.42153879298736974 + Standard Deviation: 0.24422086212708746 + Quartiles: [0, 0, 0, 1, 2] + +rename> + Total Samples: 37133 + Total Execution Time: 15709 + Average Execution Time: 0.42304688551961867 + Standard Deviation: 0.24423979951447622 + Quartiles: [0, 0, 0, 1, 2] + +rename> + Total Samples: 37133 + Total Execution Time: 15545 + Average Execution Time: 0.41863032881803247 + Standard Deviation: 0.24337897661176244 + Quartiles: [0, 0, 0, 1, 1] + +rename + Total Samples: 37133 + Total Execution Time: 15665 + Average Execution Time: 0.4218619556728516 + Standard Deviation: 0.24432532960936118 + Quartiles: [0, 0, 0, 1, 2] + +store_temp> + Total Samples: 13 + Total Execution Time: 7 + Average Execution Time: 0.5384615384615384 + Standard Deviation: 0.24852071005917167 + Quartiles: [0, 0, 1, 1, 1] + +print + Total Samples: 12 + Total Execution Time: 861 + Average Execution Time: 71.75 + Standard Deviation: 98.85416666666667 + Quartiles: [62, 64, 67, 79, 96] + +const_as_immediate> + Total Samples: 9269 + Total Execution Time: 3892 + Average Execution Time: 0.41989427122666956 + Standard Deviation: 0.24379884522449477 + Quartiles: [0, 0, 0, 1, 2] + +u8_overflowing_sub + Total Samples: 8602 + Total Execution Time: 3573 + Average Execution Time: 0.4153685189490816 + Standard Deviation: 0.24307001648395704 + Quartiles: [0, 0, 0, 1, 2] + +u8_overflowing_add + Total Samples: 667 + Total Execution Time: 271 + Average Execution Time: 0.4062968515742129 + Standard Deviation: 0.24121971997509528 + Quartiles: [0, 0, 0, 1, 1] + +const_as_immediate> + Total Samples: 5298 + Total Execution Time: 2168 + Average Execution Time: 0.4092110230275576 + Standard Deviation: 0.24175736166029918 + Quartiles: [0, 0, 0, 1, 1] + +felt252_sub + Total Samples: 2648 + Total Execution Time: 1366 + Average Execution Time: 0.5158610271903323 + Standard Deviation: 0.24974842781645212 + Quartiles: [0, 0, 1, 1, 1] + +rename + Total Samples: 15245 + Total Execution Time: 6468 + Average Execution Time: 0.424270252541817 + Standard Deviation: 0.24465857701281557 + Quartiles: [0, 0, 0, 1, 2] + +felt252_add + Total Samples: 2651 + Total Execution Time: 1337 + Average Execution Time: 0.5043379856657865 + Standard Deviation: 0.2499811818803701 + Quartiles: [0, 0, 1, 1, 1] + +felt252_dict_squash + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + +store_temp> + Total Samples: 1 + Total Execution Time: 1 + Average Execution Time: 1 + Standard Deviation: 0 + Quartiles: [1, 1, 1, 1, 1] + diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index e947278f3..36d9fb284 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -3,8 +3,6 @@ use cairo_lang_compiler::{ compile_prepared_db, db::RootDatabase, project::setup_project, CompilerConfig, }; use cairo_lang_runner::short_string::as_cairo_short_string; -#[cfg(feature = "with-trace-dump")] -use cairo_lang_sierra::ids::ConcreteLibfuncId; use cairo_lang_sierra_to_casm::metadata::MetadataComputationConfig; use cairo_native::{ context::NativeContext, @@ -16,6 +14,10 @@ use clap::{Parser, ValueEnum}; use std::path::PathBuf; use tracing_subscriber::{EnvFilter, FmtSubscriber}; use utils::{find_function, result_to_runresult}; +#[cfg(feature = "with-libfunc-profiling")] +use { + cairo_lang_sierra::ids::ConcreteLibfuncId, cairo_native::metadata::profiler::LibfuncProfiles, +}; mod utils; @@ -179,7 +181,7 @@ fn main() -> anyhow::Result<()> { LIBFUNC_PROFILE .lock() .unwrap() - .insert(0, ProfileImpl::new(sierra_program.clone())); + .insert(0, ProfileImpl::new()); } let gas_metadata = @@ -232,11 +234,11 @@ fn main() -> anyhow::Result<()> { if let Some(profiler_output_path) = args.profiler_output { let mut output = File::create(profiler_output_path)?; - let mut processed_profile = profile.summarize_profiles(process_profiles); + let raw_profiles = profile.get_profiles(&sierra_program); + let mut processed_profiles = process_profiles(raw_profiles); - processed_profile.sort_by_key(|LibfuncProfileSummary { libfunc_idx, .. }| { - profile - .sierra_program() + processed_profiles.sort_by_key(|LibfuncProfileSummary { libfunc_idx, .. }| { + sierra_program .libfunc_declarations .iter() .enumerate() @@ -251,7 +253,7 @@ fn main() -> anyhow::Result<()> { average_time, std_deviation, quartiles, - } in processed_profile + } in processed_profiles { writeln!(output, "{libfunc_idx}")?; writeln!(output, " Total Samples: {samples}")?; @@ -282,9 +284,6 @@ fn main() -> anyhow::Result<()> { Ok(()) } -/// This represents a libfunc's profile, which has the following structure: -/// -/// `Vec<(libfunc_id, (samples_number, total_execution_time, quartiles, average_execution_time, standard_deviations))>`` #[cfg(feature = "with-libfunc-profiling")] pub struct LibfuncProfileSummary { pub libfunc_idx: ConcreteLibfuncId, @@ -295,66 +294,71 @@ pub struct LibfuncProfileSummary { pub quartiles: [u64; 5], } -#[cfg(feature = "with-trace-dump")] -fn process_profiles(profile: (ConcreteLibfuncId, (Vec, u64))) -> LibfuncProfileSummary { - let (libfunc_idx, (mut tick_deltas, extra_count)) = profile; - - // if no deltas were registered, we only return the libfunc's calls amount - if tick_deltas.is_empty() { - return LibfuncProfileSummary { - libfunc_idx, - samples: extra_count, - total_time: 0, - average_time: 0.0, - std_deviation: 0.0, - quartiles: [0; 5], - }; - } - - tick_deltas.sort(); +#[cfg(feature = "with-libfunc-profiling")] +fn process_profiles(profiles: LibfuncProfiles) -> Vec { + profiles + .into_iter() + .map(|(libfunc_idx, (mut tick_deltas, extra_count))| { + // if no deltas were registered, we only return the libfunc's calls amount + if tick_deltas.is_empty() { + return LibfuncProfileSummary { + libfunc_idx, + samples: extra_count, + total_time: 0, + average_time: 0.0, + std_deviation: 0.0, + quartiles: [0; 5], + }; + } - // Drop outliers. - { - let q1 = tick_deltas[tick_deltas.len() / 4]; - let q3 = tick_deltas[3 * tick_deltas.len() / 4]; - let iqr = q3 - q1; + tick_deltas.sort(); - let q1_thr = q1.saturating_sub(iqr + iqr / 2); - let q3_thr = q3 + (iqr + iqr / 2); + // Drop outliers. + { + let q1 = tick_deltas[tick_deltas.len() / 4]; + let q3 = tick_deltas[3 * tick_deltas.len() / 4]; + let iqr = q3 - q1; - tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); - } + let q1_thr = q1.saturating_sub(iqr + iqr / 2); + let q3_thr = q3 + (iqr + iqr / 2); - // Compute the quartiles. - let quartiles = [ - *tick_deltas.first().unwrap(), - tick_deltas[tick_deltas.len() / 4], - tick_deltas[tick_deltas.len() / 2], - tick_deltas[3 * tick_deltas.len() / 4], - *tick_deltas.last().unwrap(), - ]; - - // Compuite the average. - let average = tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; - - // Compute the standard deviation. - let std_dev = { - let sum = tick_deltas - .iter() - .copied() - .map(|x| x as f64) - .map(|x| (x - average)) - .map(|x| x * x) - .sum::(); - sum / (tick_deltas.len() as u64 + extra_count) as f64 - }; + tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); + } - LibfuncProfileSummary { - libfunc_idx, - samples: tick_deltas.len() as u64 + extra_count, - total_time: tick_deltas.iter().sum::() + (extra_count as f64 * average).round() as u64, - average_time: average, - std_deviation: std_dev, - quartiles, - } + // Compute the quartiles. + let quartiles = [ + *tick_deltas.first().unwrap(), + tick_deltas[tick_deltas.len() / 4], + tick_deltas[tick_deltas.len() / 2], + tick_deltas[3 * tick_deltas.len() / 4], + *tick_deltas.last().unwrap(), + ]; + + // Compuite the average. + let average = + tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; + + // Compute the standard deviation. + let std_dev = { + let sum = tick_deltas + .iter() + .copied() + .map(|x| x as f64) + .map(|x| (x - average)) + .map(|x| x * x) + .sum::(); + sum / (tick_deltas.len() as u64 + extra_count) as f64 + }; + + LibfuncProfileSummary { + libfunc_idx, + samples: tick_deltas.len() as u64 + extra_count, + total_time: tick_deltas.iter().sum::() + + (extra_count as f64 * average).round() as u64, + average_time: average, + std_deviation: std_dev, + quartiles, + } + }) + .collect::>() } diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 241d07d5d..a4aa4b854 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -319,24 +319,24 @@ impl ProfilerMeta { } } +/// Represents a libfunc's profile. A libfunc profile maps libfuncs id +/// to a tuple with a vector of deltas (*1) and extra counts (*2). +/// *1 Each delta refers to the execution time of that libfunc call +/// *2 `extra_count` is a count of libfunc calls whose execution time +/// couldn't be calculated. +pub type LibfuncProfiles = HashMap, u64)>; + pub static LIBFUNC_PROFILE: LazyLock>> = LazyLock::new(|| Mutex::new(HashMap::new())); +#[derive(Default)] pub struct ProfileImpl { pub trace: Vec<(StatementIdx, u64)>, - sierra_program: Program, } impl ProfileImpl { - pub fn new(sierra_program: Program) -> Self { - Self { - trace: Vec::new(), - sierra_program, - } - } - - pub fn sierra_program(&self) -> &Program { - &self.sierra_program + pub fn new() -> Self { + Self { trace: Vec::new() } } // Push a profiler frame @@ -361,16 +361,11 @@ impl ProfileImpl { /// `extra_count`: counter of libfunc calls whose execution time /// hasn't been calculated for being invalid. /// - pub fn summarize_profiles(&self, processor: F) -> Vec - where - F: FnMut((ConcreteLibfuncId, (Vec, u64))) -> R, - { + pub fn get_profiles(&self, sierra_program: &Program) -> LibfuncProfiles { let mut trace = HashMap::, u64)>::new(); for (statement_idx, tick_delta) in self.trace.iter() { - if let Statement::Invocation(invocation) = - &self.sierra_program.statements[statement_idx.0] - { + if let Statement::Invocation(invocation) = &sierra_program.statements[statement_idx.0] { let (tick_deltas, extra_count) = trace.entry(invocation.libfunc_id.clone()).or_default(); @@ -384,7 +379,7 @@ impl ProfileImpl { } } - trace.into_iter().map(processor).collect::>() + trace } } From d1f3594ae9e2598aa78d4631e5c7bd267b77cffd Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Thu, 12 Jun 2025 15:28:33 -0300 Subject: [PATCH 23/27] remove closure and return raw data --- profile.md | 784 ----------------------------------------------------- 1 file changed, 784 deletions(-) delete mode 100644 profile.md diff --git a/profile.md b/profile.md deleted file mode 100644 index 4a3414394..000000000 --- a/profile.md +++ /dev/null @@ -1,784 +0,0 @@ -alloc_local> - Total Samples: 17970 - Total Execution Time: 7543 - Average Execution Time: 0.41975514746800224 - Standard Deviation: 0.2435607636421274 - Quartiles: [0, 0, 0, 1, 1] - -finalize_locals - Total Samples: 17969 - Total Execution Time: 7683 - Average Execution Time: 0.42756970337803996 - Standard Deviation: 0.24475385213129322 - Quartiles: [0, 0, 0, 1, 1] - -disable_ap_tracking - Total Samples: 29305 - Total Execution Time: 12420 - Average Execution Time: 0.4238184610134789 - Standard Deviation: 0.24433286859624354 - Quartiles: [0, 0, 0, 1, 2] - -felt252_dict_new - Total Samples: 2 - Total Execution Time: 6 - Average Execution Time: 3 - Standard Deviation: 0 - Quartiles: [3, 3, 3, 3, 3] - -const_as_immediate> - Total Samples: 3 - Total Execution Time: 3 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -store_temp - Total Samples: 75707 - Total Execution Time: 31709 - Average Execution Time: 0.4188384165268733 - Standard Deviation: 0.24367697373231473 - Quartiles: [0, 0, 0, 1, 2] - -store_temp - Total Samples: 17977 - Total Execution Time: 7561 - Average Execution Time: 0.42059297991878514 - Standard Deviation: 0.2444732980382943 - Quartiles: [0, 0, 0, 1, 2] - -store_temp - Total Samples: 59872 - Total Execution Time: 25452 - Average Execution Time: 0.42510689470871194 - Standard Deviation: 0.24469166414817833 - Quartiles: [0, 0, 0, 1, 2] - -store_temp - Total Samples: 89921 - Total Execution Time: 38120 - Average Execution Time: 0.4239276698435293 - Standard Deviation: 0.24443541804007066 - Quartiles: [0, 0, 0, 1, 2] - -store_temp>> - Total Samples: 17970 - Total Execution Time: 7598 - Average Execution Time: 0.4228158041179744 - Standard Deviation: 0.24437648972239143 - Quartiles: [0, 0, 0, 1, 2] - -store_temp> - Total Samples: 50810 - Total Execution Time: 21632 - Average Execution Time: 0.42574296398346784 - Standard Deviation: 0.24464334192323936 - Quartiles: [0, 0, 0, 1, 2] - -enum_match, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>> - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -branch_align - Total Samples: 153552 - Total Execution Time: 64758 - Average Execution Time: 0.42173335417317914 - Standard Deviation: 0.24421297964471228 - Quartiles: [0, 0, 0, 1, 2] - -redeposit_gas - Total Samples: 32021 - Total Execution Time: 32021 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -struct_deconstruct, u32, Felt252Dict, u32, Unit>> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -drop - Total Samples: 17981 - Total Execution Time: 7587 - Average Execution Time: 0.4219453867971748 - Standard Deviation: 0.24412993439568562 - Quartiles: [0, 0, 0, 1, 2] - -drop - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -store_local> - Total Samples: 17966 - Total Execution Time: 7590 - Average Execution Time: 0.4224646554603139 - Standard Deviation: 0.24432223450166501 - Quartiles: [0, 0, 0, 1, 2] - -drop> - Total Samples: 2 - Total Execution Time: 90 - Average Execution Time: 45 - Standard Deviation: 576 - Quartiles: [21, 21, 69, 69, 69] - -drop>> - Total Samples: 2 - Total Execution Time: 2 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -alloc_local>> - Total Samples: 53838 - Total Execution Time: 22820 - Average Execution Time: 0.4238641851480367 - Standard Deviation: 0.24442622859166338 - Quartiles: [0, 0, 0, 1, 2] - -alloc_local> - Total Samples: 2 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -felt252_dict_new - Total Samples: 1 - Total Execution Time: 17 - Average Execution Time: 17 - Standard Deviation: 0 - Quartiles: [17, 17, 17, 17, 17] - -dup>> - Total Samples: 35928 - Total Execution Time: 18903 - Average Execution Time: 0.5261356045424181 - Standard Deviation: 0.2517106064167782 - Quartiles: [0, 0, 1, 1, 2] - -store_local> - Total Samples: 2 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -drop>>> - Total Samples: 53837 - Total Execution Time: 22624 - Average Execution Time: 0.4202314393446886 - Standard Deviation: 0.24411991597371122 - Quartiles: [0, 0, 0, 1, 2] - -const_as_immediate> - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -store_temp - Total Samples: 35793 - Total Execution Time: 15108 - Average Execution Time: 0.4220937054731372 - Standard Deviation: 0.2443776240524776 - Quartiles: [0, 0, 0, 1, 2] - -store_temp> - Total Samples: 59650 - Total Execution Time: 25189 - Average Execution Time: 0.4222799664710813 - Standard Deviation: 0.24412724098178706 - Quartiles: [0, 0, 0, 1, 2] - -store_temp>> - Total Samples: 17897 - Total Execution Time: 7623 - Average Execution Time: 0.42593730792870316 - Standard Deviation: 0.2449617199341363 - Quartiles: [0, 0, 0, 1, 2] - -enum_match, core::dict::Felt252Dict::, core::integer::u32, ())>> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -struct_deconstruct, Felt252Dict, u32, Unit>> - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -drop - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -drop> - Total Samples: 1 - Total Execution Time: 18 - Average Execution Time: 18 - Standard Deviation: 0 - Quartiles: [18, 18, 18, 18, 18] - -struct_construct> - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -enum_init, 0> - Total Samples: 1 - Total Execution Time: 2 - Average Execution Time: 2 - Standard Deviation: 0 - Quartiles: [2, 2, 2, 2, 2] - -store_temp> - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -drop>> - Total Samples: 1 - Total Execution Time: 6 - Average Execution Time: 6 - Standard Deviation: 0 - Quartiles: [6, 6, 6, 6, 6] - -drop>> - Total Samples: 2 - Total Execution Time: 19 - Average Execution Time: 9.5 - Standard Deviation: 72.25 - Quartiles: [1, 1, 18, 18, 18] - -alloc_local> - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -array_new - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -const_as_immediate> - Total Samples: 12607 - Total Execution Time: 5308 - Average Execution Time: 0.4210359324184977 - Standard Deviation: 0.2437646760309274 - Quartiles: [0, 0, 0, 1, 1] - -store_temp - Total Samples: 29953 - Total Execution Time: 12634 - Average Execution Time: 0.4217941441591827 - Standard Deviation: 0.24401738666220757 - Quartiles: [0, 0, 0, 1, 2] - -array_append - Total Samples: 70 - Total Execution Time: 27 - Average Execution Time: 0.38571428571428573 - Standard Deviation: 0.2655102040816325 - Quartiles: [0, 0, 0, 1, 2] - -const_as_immediate> - Total Samples: 3390 - Total Execution Time: 1469 - Average Execution Time: 0.43333333333333335 - Standard Deviation: 0.24614552605703674 - Quartiles: [0, 0, 0, 1, 2] - -const_as_immediate> - Total Samples: 11950 - Total Execution Time: 5134 - Average Execution Time: 0.4296234309623431 - Standard Deviation: 0.24521450254726676 - Quartiles: [0, 0, 0, 1, 2] - -const_as_immediate> - Total Samples: 17911 - Total Execution Time: 7593 - Average Execution Time: 0.4239294288426107 - Standard Deviation: 0.24432493142757067 - Quartiles: [0, 0, 0, 1, 2] - -const_as_immediate> - Total Samples: 15254 - Total Execution Time: 6333 - Average Execution Time: 0.4151697915300905 - Standard Deviation: 0.24293494888160955 - Quartiles: [0, 0, 0, 1, 2] - -const_as_immediate> - Total Samples: 1397 - Total Execution Time: 572 - Average Execution Time: 0.4094488188976378 - Standard Deviation: 0.24180048360096582 - Quartiles: [0, 0, 0, 1, 1] - -const_as_immediate> - Total Samples: 3338 - Total Execution Time: 1430 - Average Execution Time: 0.4284002396644697 - Standard Deviation: 0.2454726354942492 - Quartiles: [0, 0, 0, 1, 2] - -store_local> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -snapshot_take> - Total Samples: 1 - Total Execution Time: 48 - Average Execution Time: 48 - Standard Deviation: 0 - Quartiles: [48, 48, 48, 48, 48] - -drop> - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -struct_construct - Total Samples: 3 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -enum_init>, 1> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -withdraw_gas - Total Samples: 15796 - Total Execution Time: 15796 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -array_len - Total Samples: 17970 - Total Execution Time: 10129 - Average Execution Time: 0.5636616583194213 - Standard Deviation: 0.24639237968183855 - Quartiles: [0, 0, 1, 1, 2] - -dup - Total Samples: 37948 - Total Execution Time: 16114 - Average Execution Time: 0.4246337092863919 - Standard Deviation: 0.2447942555222798 - Quartiles: [0, 0, 0, 1, 2] - -u32_overflowing_sub - Total Samples: 19295 - Total Execution Time: 8898 - Average Execution Time: 0.46115573982897123 - Standard Deviation: 0.24911304622966463 - Quartiles: [0, 0, 0, 1, 2] - -struct_construct, u32, Felt252Dict, u32, Unit>> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -enum_init, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>, 0> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -store_temp, core::integer::u32, core::dict::Felt252Dict::, core::integer::u32, ())>> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -array_get - Total Samples: 17279 - Total Execution Time: 17279 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -store_temp> - Total Samples: 17967 - Total Execution Time: 7612 - Average Execution Time: 0.42366560917237156 - Standard Deviation: 0.24461832153274635 - Quartiles: [0, 0, 0, 1, 2] - -unbox - Total Samples: 17130 - Total Execution Time: 17130 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -rename - Total Samples: 17968 - Total Execution Time: 7770 - Average Execution Time: 0.43243544078361534 - Standard Deviation: 0.24554633933171735 - Quartiles: [0, 0, 0, 1, 2] - -enable_ap_tracking - Total Samples: 11331 - Total Execution Time: 4734 - Average Execution Time: 0.4177918983320095 - Standard Deviation: 0.24341833494801057 - Quartiles: [0, 0, 0, 1, 2] - -dup - Total Samples: 80294 - Total Execution Time: 33952 - Average Execution Time: 0.4228460408000598 - Standard Deviation: 0.24444580196201987 - Quartiles: [0, 0, 0, 1, 2] - -u8_eq - Total Samples: 69091 - Total Execution Time: 29231 - Average Execution Time: 0.42307970647407045 - Standard Deviation: 0.24440168907756138 - Quartiles: [0, 0, 0, 1, 2] - -jump - Total Samples: 61088 - Total Execution Time: 25716 - Average Execution Time: 0.4209664745940283 - Standard Deviation: 0.24404835875042852 - Quartiles: [0, 0, 0, 1, 2] - -u32_to_felt252 - Total Samples: 2002 - Total Execution Time: 906 - Average Execution Time: 0.45254745254745254 - Standard Deviation: 0.2477482557402536 - Quartiles: [0, 0, 0, 1, 1] - -felt252_dict_entry_get - Total Samples: 1984 - Total Execution Time: 18861 - Average Execution Time: 9.506552419354838 - Standard Deviation: 0.30741674321995127 - Quartiles: [8, 9, 9, 10, 11] - -felt252_dict_entry_finalize - Total Samples: 2002 - Total Execution Time: 928 - Average Execution Time: 0.46353646353646355 - Standard Deviation: 0.2486704105085778 - Quartiles: [0, 0, 0, 1, 1] - -drop - Total Samples: 27168 - Total Execution Time: 11416 - Average Execution Time: 0.4202002355712603 - Standard Deviation: 0.24422092574794188 - Quartiles: [0, 0, 0, 1, 2] - -const_as_immediate> - Total Samples: 19293 - Total Execution Time: 8115 - Average Execution Time: 0.42061887731301506 - Standard Deviation: 0.2439059664440165 - Quartiles: [0, 0, 0, 1, 2] - -u32_overflowing_add - Total Samples: 17968 - Total Execution Time: 8251 - Average Execution Time: 0.4592052537845058 - Standard Deviation: 0.24866971566244478 - Quartiles: [0, 0, 0, 1, 2] - -felt252_dict_squash - Total Samples: 2 - Total Execution Time: 51 - Average Execution Time: 25.5 - Standard Deviation: 56.25 - Quartiles: [18, 18, 33, 33, 33] - -store_temp> - Total Samples: 2 - Total Execution Time: 1 - Average Execution Time: 0.5 - Standard Deviation: 0.25 - Quartiles: [0, 0, 1, 1, 1] - -alloc_local> - Total Samples: 17897 - Total Execution Time: 7587 - Average Execution Time: 0.4239257976197128 - Standard Deviation: 0.2443244663048958 - Quartiles: [0, 0, 0, 1, 2] - -alloc_local - Total Samples: 17896 - Total Execution Time: 7570 - Average Execution Time: 0.42299955297273134 - Standard Deviation: 0.24485322887778174 - Quartiles: [0, 0, 0, 1, 2] - -drop> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -drop>> - Total Samples: 16572 - Total Execution Time: 6905 - Average Execution Time: 0.4166666666666667 - Standard Deviation: 0.24341761203637532 - Quartiles: [0, 0, 0, 1, 2] - -struct_construct, Felt252Dict, u32, Unit>> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -enum_init, core::dict::Felt252Dict::, core::integer::u32, ())>, 0> - Total Samples: 1 - Total Execution Time: 5 - Average Execution Time: 5 - Standard Deviation: 0 - Quartiles: [5, 5, 5, 5, 5] - -store_temp, core::dict::Felt252Dict::, core::integer::u32, ())>> - Total Samples: 1 - Total Execution Time: 0 - Average Execution Time: 0 - Standard Deviation: 0 - Quartiles: [0, 0, 0, 0, 0] - -store_local - Total Samples: 17896 - Total Execution Time: 7659 - Average Execution Time: 0.4279727313366115 - Standard Deviation: 0.24537085665477268 - Quartiles: [0, 0, 0, 1, 2] - -const_as_immediate> - Total Samples: 3315 - Total Execution Time: 1365 - Average Execution Time: 0.4117647058823529 - Standard Deviation: 0.24221453287196662 - Quartiles: [0, 0, 0, 1, 1] - -array_new - Total Samples: 13 - Total Execution Time: 4 - Average Execution Time: 0.3076923076923077 - Standard Deviation: 0.21301775147928995 - Quartiles: [0, 0, 0, 1, 1] - -array_append - Total Samples: 12 - Total Execution Time: 20 - Average Execution Time: 1.6666666666666667 - Standard Deviation: 0.2222222222222223 - Quartiles: [1, 1, 2, 2, 2] - -u8_to_felt252 - Total Samples: 13 - Total Execution Time: 7 - Average Execution Time: 0.5384615384615384 - Standard Deviation: 0.24852071005917167 - Quartiles: [0, 0, 1, 1, 1] - -store_local> - Total Samples: 1325 - Total Execution Time: 597 - Average Execution Time: 0.4505660377358491 - Standard Deviation: 0.24755628337487107 - Quartiles: [0, 0, 0, 1, 1] - -dup - Total Samples: 20540 - Total Execution Time: 8611 - Average Execution Time: 0.41923076923076924 - Standard Deviation: 0.2437684443112503 - Quartiles: [0, 0, 0, 1, 2] - -felt252_dict_entry_get - Total Samples: 20467 - Total Execution Time: 192907 - Average Execution Time: 9.425269946743539 - Standard Deviation: 0.2973787259267783 - Quartiles: [8, 9, 9, 10, 11] - -felt252_dict_entry_finalize - Total Samples: 20541 - Total Execution Time: 9201 - Average Execution Time: 0.4479334014897035 - Standard Deviation: 0.24767853429206335 - Quartiles: [0, 0, 0, 1, 2] - -u8_is_zero - Total Samples: 1990 - Total Execution Time: 862 - Average Execution Time: 0.43316582914572865 - Standard Deviation: 0.2455331936062132 - Quartiles: [0, 0, 0, 1, 1] - -drop> - Total Samples: 1325 - Total Execution Time: 553 - Average Execution Time: 0.41735849056603774 - Standard Deviation: 0.24317038091847656 - Quartiles: [0, 0, 0, 1, 1] - -rename - Total Samples: 37133 - Total Execution Time: 15645 - Average Execution Time: 0.42132335119704845 - Standard Deviation: 0.24391770582824324 - Quartiles: [0, 0, 0, 1, 2] - -rename - Total Samples: 37133 - Total Execution Time: 15653 - Average Execution Time: 0.42153879298736974 - Standard Deviation: 0.24422086212708746 - Quartiles: [0, 0, 0, 1, 2] - -rename> - Total Samples: 37133 - Total Execution Time: 15709 - Average Execution Time: 0.42304688551961867 - Standard Deviation: 0.24423979951447622 - Quartiles: [0, 0, 0, 1, 2] - -rename> - Total Samples: 37133 - Total Execution Time: 15545 - Average Execution Time: 0.41863032881803247 - Standard Deviation: 0.24337897661176244 - Quartiles: [0, 0, 0, 1, 1] - -rename - Total Samples: 37133 - Total Execution Time: 15665 - Average Execution Time: 0.4218619556728516 - Standard Deviation: 0.24432532960936118 - Quartiles: [0, 0, 0, 1, 2] - -store_temp> - Total Samples: 13 - Total Execution Time: 7 - Average Execution Time: 0.5384615384615384 - Standard Deviation: 0.24852071005917167 - Quartiles: [0, 0, 1, 1, 1] - -print - Total Samples: 12 - Total Execution Time: 861 - Average Execution Time: 71.75 - Standard Deviation: 98.85416666666667 - Quartiles: [62, 64, 67, 79, 96] - -const_as_immediate> - Total Samples: 9269 - Total Execution Time: 3892 - Average Execution Time: 0.41989427122666956 - Standard Deviation: 0.24379884522449477 - Quartiles: [0, 0, 0, 1, 2] - -u8_overflowing_sub - Total Samples: 8602 - Total Execution Time: 3573 - Average Execution Time: 0.4153685189490816 - Standard Deviation: 0.24307001648395704 - Quartiles: [0, 0, 0, 1, 2] - -u8_overflowing_add - Total Samples: 667 - Total Execution Time: 271 - Average Execution Time: 0.4062968515742129 - Standard Deviation: 0.24121971997509528 - Quartiles: [0, 0, 0, 1, 1] - -const_as_immediate> - Total Samples: 5298 - Total Execution Time: 2168 - Average Execution Time: 0.4092110230275576 - Standard Deviation: 0.24175736166029918 - Quartiles: [0, 0, 0, 1, 1] - -felt252_sub - Total Samples: 2648 - Total Execution Time: 1366 - Average Execution Time: 0.5158610271903323 - Standard Deviation: 0.24974842781645212 - Quartiles: [0, 0, 1, 1, 1] - -rename - Total Samples: 15245 - Total Execution Time: 6468 - Average Execution Time: 0.424270252541817 - Standard Deviation: 0.24465857701281557 - Quartiles: [0, 0, 0, 1, 2] - -felt252_add - Total Samples: 2651 - Total Execution Time: 1337 - Average Execution Time: 0.5043379856657865 - Standard Deviation: 0.2499811818803701 - Quartiles: [0, 0, 1, 1, 1] - -felt252_dict_squash - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - -store_temp> - Total Samples: 1 - Total Execution Time: 1 - Average Execution Time: 1 - Standard Deviation: 0 - Quartiles: [1, 1, 1, 1, 1] - From 5cb9aa72984e712459f229cf79230690d1988d00 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Thu, 12 Jun 2025 17:22:17 -0300 Subject: [PATCH 24/27] reviews --- Cargo.lock | 246 ++++++++++++++++++------------------ src/bin/cairo-native-run.rs | 141 +++++++++++---------- src/metadata/profiler.rs | 93 ++++++++------ 3 files changed, 253 insertions(+), 227 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 91d93fb47..c5fb5124d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" @@ -43,9 +43,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -58,33 +58,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.8" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", "once_cell_polyfill", @@ -108,7 +108,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -124,7 +124,7 @@ dependencies = [ "ark-std 0.5.0", "educe 0.6.0", "fnv", - "hashbrown 0.15.3", + "hashbrown 0.15.4", "itertools 0.13.0", "num-bigint", "num-integer", @@ -189,7 +189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -215,7 +215,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -230,7 +230,7 @@ dependencies = [ "ark-std 0.5.0", "educe 0.6.0", "fnv", - "hashbrown 0.15.3", + "hashbrown 0.15.4", ] [[package]] @@ -287,7 +287,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -345,9 +345,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64ct" -version = "1.7.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bincode" @@ -385,7 +385,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -451,9 +451,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "byte-slice-cast" @@ -675,7 +675,7 @@ checksum = "b1e4872352761cf6d7f47eeb1626e3b1d84a514017fb4251173148d8c04f36d5" dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -954,9 +954,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "2.12.0-dev.1" +version = "2.12.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e5e3c6be0b159dad1239fa83562087448aeb1d44b0ead059ea6ab73728909a8" +checksum = "4a7825ed2fc0acd62db7cac52e0870634e1c5ce26e7021f81cb9fce02e406669" dependencies = [ "genco", "xshell", @@ -1008,7 +1008,7 @@ version = "2.12.0-dev.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f043065d60a8a2510bfacb6c91767298fed50ed9abbd69ff7698322b7cb1e65" dependencies = [ - "hashbrown 0.15.3", + "hashbrown 0.15.4", "indexmap 2.9.0", "itertools 0.14.0", "num-bigint", @@ -1098,7 +1098,7 @@ dependencies = [ "cairo-lang-starknet", "cairo-lang-starknet-classes", "generic-array", - "hashbrown 0.15.3", + "hashbrown 0.15.4", "hex", "indoc", "keccak", @@ -1134,7 +1134,7 @@ dependencies = [ "cairo-lang-starknet", "cairo-lang-starknet-classes", "generic-array", - "hashbrown 0.15.3", + "hashbrown 0.15.4", "hex", "indoc", "keccak", @@ -1166,7 +1166,7 @@ dependencies = [ "bincode 2.0.1", "bitvec", "generic-array", - "hashbrown 0.15.3", + "hashbrown 0.15.4", "hex", "indoc", "keccak", @@ -1228,9 +1228,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.25" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "shlex", ] @@ -1246,9 +1246,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "cfg_aliases" @@ -1296,9 +1296,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.39" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", "clap_derive", @@ -1306,9 +1306,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstream", "anstyle", @@ -1318,27 +1318,27 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "colored" @@ -1639,7 +1639,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1651,7 +1651,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1718,7 +1718,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1771,9 +1771,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -1811,7 +1811,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1859,7 +1859,7 @@ checksum = "43eaff6bbc0b3a878361aced5ec6a2818ee7c541c5b33b5880dfa9a86c23e9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -1881,7 +1881,7 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] @@ -1917,9 +1917,9 @@ dependencies = [ [[package]] name = "good_lp" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1445fc8d4668eb98fee10cdb2b11bb68478c332efb0ae2893b9f15852b8079f1" +checksum = "d976304a59dd741fa234623e96473cf399e10f3f91f0487215fc561f6131d362" dependencies = [ "fnv", "microlp", @@ -1954,9 +1954,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", "equivalent", @@ -1978,9 +1978,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -2045,7 +2045,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2091,7 +2091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", - "hashbrown 0.15.3", + "hashbrown 0.15.4", "serde", ] @@ -2293,7 +2293,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.0", + "windows-targets 0.53.2", ] [[package]] @@ -2338,7 +2338,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.3", + "hashbrown 0.15.4", ] [[package]] @@ -2381,16 +2381,16 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.101", + "syn 2.0.102", "tblgen", "unindent", ] [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "microlp" @@ -2410,9 +2410,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] @@ -2618,7 +2618,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2742,9 +2742,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" @@ -2797,7 +2797,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -2850,17 +2850,17 @@ dependencies = [ [[package]] name = "proptest" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" +checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" dependencies = [ "bit-set", "bit-vec", "bitflags", "lazy_static", "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand 0.9.1", + "rand_chacha 0.9.0", "rand_xorshift", "regex-syntax 0.8.5", "rusty-fork", @@ -2956,11 +2956,11 @@ dependencies = [ [[package]] name = "rand_xorshift" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "rand_core 0.6.4", + "rand_core 0.9.3", ] [[package]] @@ -2991,9 +2991,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ "bitflags", ] @@ -3090,7 +3090,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.101", + "syn 2.0.102", "unicode-ident", ] @@ -3120,7 +3120,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3202,9 +3202,9 @@ dependencies = [ [[package]] name = "scarb-metadata" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f580d215bb85d42e9a1489aa869cae7878aff343384b73e235753334e8fb72b4" +checksum = "5c9a74ee34fdb42e20bf992f211a502d07e8b3a3abf6b1d33ccf94e5f1038314" dependencies = [ "camino", "semver", @@ -3252,7 +3252,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3301,7 +3301,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3312,7 +3312,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3329,9 +3329,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -3454,9 +3454,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smol_str" @@ -3590,9 +3590,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" dependencies = [ "proc-macro2", "quote", @@ -3658,7 +3658,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3669,7 +3669,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "test-case-core", ] @@ -3690,7 +3690,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3730,9 +3730,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -3742,18 +3742,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.26" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap 2.9.0", "serde", @@ -3765,9 +3765,9 @@ dependencies = [ [[package]] name = "toml_write" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tracing" @@ -3782,20 +3782,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -3892,7 +3892,7 @@ checksum = "35f5380909ffc31b4de4f4bdf96b877175a016aa2ca98cee39fcfd8c4d53d952" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -3933,9 +3933,9 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "unicode-xid" @@ -4012,9 +4012,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" @@ -4047,7 +4047,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasm-bindgen-shared", ] @@ -4069,7 +4069,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4170,9 +4170,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" dependencies = [ "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", @@ -4282,9 +4282,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] @@ -4345,7 +4345,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] @@ -4365,7 +4365,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.102", ] [[package]] diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index 36d9fb284..a2bc8b0a5 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -3,7 +3,11 @@ use cairo_lang_compiler::{ compile_prepared_db, db::RootDatabase, project::setup_project, CompilerConfig, }; use cairo_lang_runner::short_string::as_cairo_short_string; +#[cfg(feature = "with-libfunc-profiling")] +use cairo_lang_sierra::ids::ConcreteLibfuncId; use cairo_lang_sierra_to_casm::metadata::MetadataComputationConfig; +#[cfg(feature = "with-libfunc-profiling")] +use cairo_native::metadata::profiler::LibfuncProfileData; use cairo_native::{ context::NativeContext, executor::{AotNativeExecutor, JitNativeExecutor}, @@ -11,13 +15,11 @@ use cairo_native::{ starknet_stub::StubSyscallHandler, }; use clap::{Parser, ValueEnum}; +#[cfg(feature = "with-libfunc-profiling")] +use std::collections::HashMap; use std::path::PathBuf; use tracing_subscriber::{EnvFilter, FmtSubscriber}; use utils::{find_function, result_to_runresult}; -#[cfg(feature = "with-libfunc-profiling")] -use { - cairo_lang_sierra::ids::ConcreteLibfuncId, cairo_native::metadata::profiler::LibfuncProfiles, -}; mod utils; @@ -176,12 +178,12 @@ fn main() -> anyhow::Result<()> { #[cfg(feature = "with-libfunc-profiling")] { - use cairo_native::metadata::profiler::{ProfileImpl, LIBFUNC_PROFILE}; + use cairo_native::metadata::profiler::{ProfilerImpl, LIBFUNC_PROFILE}; LIBFUNC_PROFILE .lock() .unwrap() - .insert(0, ProfileImpl::new()); + .insert(0, ProfilerImpl::new()); } let gas_metadata = @@ -234,7 +236,7 @@ fn main() -> anyhow::Result<()> { if let Some(profiler_output_path) = args.profiler_output { let mut output = File::create(profiler_output_path)?; - let raw_profiles = profile.get_profiles(&sierra_program); + let raw_profiles = profile.get_profile(&sierra_program); let mut processed_profiles = process_profiles(raw_profiles); processed_profiles.sort_by_key(|LibfuncProfileSummary { libfunc_idx, .. }| { @@ -295,70 +297,79 @@ pub struct LibfuncProfileSummary { } #[cfg(feature = "with-libfunc-profiling")] -fn process_profiles(profiles: LibfuncProfiles) -> Vec { +fn process_profiles( + profiles: HashMap, +) -> Vec { profiles .into_iter() - .map(|(libfunc_idx, (mut tick_deltas, extra_count))| { - // if no deltas were registered, we only return the libfunc's calls amount - if tick_deltas.is_empty() { - return LibfuncProfileSummary { - libfunc_idx, - samples: extra_count, - total_time: 0, - average_time: 0.0, - std_deviation: 0.0, - quartiles: [0; 5], - }; - } + .map( + |( + libfunc_idx, + LibfuncProfileData { + mut deltas, + extra_counts, + }, + )| { + // if no deltas were registered, we only return the libfunc's calls amount + if deltas.is_empty() { + return LibfuncProfileSummary { + libfunc_idx, + samples: extra_counts, + total_time: 0, + average_time: 0.0, + std_deviation: 0.0, + quartiles: [0; 5], + }; + } - tick_deltas.sort(); + deltas.sort(); - // Drop outliers. - { - let q1 = tick_deltas[tick_deltas.len() / 4]; - let q3 = tick_deltas[3 * tick_deltas.len() / 4]; - let iqr = q3 - q1; + // Drop outliers. + { + let q1 = deltas[deltas.len() / 4]; + let q3 = deltas[3 * deltas.len() / 4]; + let iqr = q3 - q1; - let q1_thr = q1.saturating_sub(iqr + iqr / 2); - let q3_thr = q3 + (iqr + iqr / 2); + let q1_thr = q1.saturating_sub(iqr + iqr / 2); + let q3_thr = q3 + (iqr + iqr / 2); - tick_deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); - } + deltas.retain(|x| *x >= q1_thr && *x <= q3_thr); + } - // Compute the quartiles. - let quartiles = [ - *tick_deltas.first().unwrap(), - tick_deltas[tick_deltas.len() / 4], - tick_deltas[tick_deltas.len() / 2], - tick_deltas[3 * tick_deltas.len() / 4], - *tick_deltas.last().unwrap(), - ]; - - // Compuite the average. - let average = - tick_deltas.iter().copied().sum::() as f64 / tick_deltas.len() as f64; - - // Compute the standard deviation. - let std_dev = { - let sum = tick_deltas - .iter() - .copied() - .map(|x| x as f64) - .map(|x| (x - average)) - .map(|x| x * x) - .sum::(); - sum / (tick_deltas.len() as u64 + extra_count) as f64 - }; - - LibfuncProfileSummary { - libfunc_idx, - samples: tick_deltas.len() as u64 + extra_count, - total_time: tick_deltas.iter().sum::() - + (extra_count as f64 * average).round() as u64, - average_time: average, - std_deviation: std_dev, - quartiles, - } - }) + // Compute the quartiles. + let quartiles = [ + *deltas.first().unwrap(), + deltas[deltas.len() / 4], + deltas[deltas.len() / 2], + deltas[3 * deltas.len() / 4], + *deltas.last().unwrap(), + ]; + + // Compuite the average. + let average = deltas.iter().copied().sum::() as f64 / deltas.len() as f64; + + // Compute the standard deviation. + let std_dev = { + let sum = deltas + .iter() + .copied() + .map(|x| x as f64) + .map(|x| (x - average)) + .map(|x| x * x) + .sum::(); + sum / (deltas.len() as u64 + extra_counts) as f64 + }; + + LibfuncProfileSummary { + libfunc_idx, + samples: deltas.len() as u64 + extra_counts, + total_time: deltas.iter().sum::() + + (extra_counts as f64 * average).round() as u64, + average_time: average, + std_deviation: std_dev, + quartiles, + } + }, + ) .collect::>() } diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index a4aa4b854..6c0494876 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -5,19 +5,20 @@ //! 1. `measure_timestamp`: called before every libfunc execution. //! //! 2. `push_frame`: called before every branching operation. This method will also call `measure_timestamp`. This, -//! with the timestamp calculated before the execution, will allow to measure each libfunc's execution time. Apart -//! from that, it will count every libfunc's call, allowing to summarize every libfun'c execution execution time. +//! with the timestamp calculated before the execution, will allow to measure each statement's execution time. +//! If for some reason, the statement delta time could not be gathered, we just record an unit value, recording that +//! we executed the given statement. //! -//! Once the program execution finished and the information was gathered, a `summarize_profiles` can be called. It -//! exepects a closure to process this information. +//! Once the program execution finished and the information was gathered, the `get_profile` method can be called. +//! It groups the samples by libfunc, and returns all data related to each libfunc. //! -//! As well as with the trace-dump fature, in the context of starknet contracts, we need to add support for building -//! profiles for multiple programs. To do so, we need two important elements, which must be set before every contract +//! As well as with the trace-dump feature, in the context of Starknet contracts, we need to add support for building +//! profiles for multiple executions. To do so, we need two important elements, which must be set before every contract //! execution: //! -//! 1. A glbal static hashmap to map every profile id to its respective profile summary. See `LIBFUNC_PROFILE`. +//! 1. A golbal static hashmap to map every profile ID to its respective profiler. See `LIBFUNC_PROFILE`. //! -//! 2. A counter to track the ID of the current libfunc profile, which gets updated every time we switch to another +//! 2. A counter to track the ID of the current profiler, which gets updated every time we switch to another //! contract. Since a contract can call other contract's, we need a way of restoring the counter after every execution. //! //! See cairo-native-run` for an example on how to do it. @@ -44,7 +45,7 @@ use melior::{ }, Context, }; -#[cfg(feature = "with-libfunc-profiling")] + use std::{ cell::RefCell, collections::{HashMap, HashSet}, @@ -69,7 +70,7 @@ impl ProfilerBinding { const fn function_ptr(self) -> *const () { match self { - ProfilerBinding::PushStmt => ProfileImpl::push_stmt as *const (), + ProfilerBinding::PushStmt => ProfilerImpl::push_stmt as *const (), ProfilerBinding::ProfileId => ptr::null(), } } @@ -168,8 +169,9 @@ impl ProfilerMeta { block.append_op_result(memref::load(trace_profile_ptr, &[], location)) } - /// Get the timestamp - /// Values + /// Gets the current timestamp. + /// + /// The values returned are: /// 1. Timestamp /// 2. CPU's id core in which the program is running (only for x86 arch) /// @@ -224,8 +226,9 @@ impl ProfilerMeta { Ok((value, core_idx)) } - /// Get the timestamp - /// Values + /// Gets the current timestamp. + /// + /// The values returned are: /// 1. Timestamp /// 2. CPU's id core in which the program is running (only for x86 arch) /// @@ -324,62 +327,74 @@ impl ProfilerMeta { /// *1 Each delta refers to the execution time of that libfunc call /// *2 `extra_count` is a count of libfunc calls whose execution time /// couldn't be calculated. -pub type LibfuncProfiles = HashMap, u64)>; +/// Represents the entire profile of the execution. +/// +///It maps the libfunc ID to a libfunc profile. +type Profile = HashMap; + +/// Represents the profile data for a particular libfunc. +#[derive(Default)] +pub struct LibfuncProfileData { + /// A vector of execution times, for each time the libfunc was executed. + pub deltas: Vec, + /// If the time delta for a particular execution could not be gathered, + /// we just increase `extra_counts` by 1. + pub extra_counts: u64, +} -pub static LIBFUNC_PROFILE: LazyLock>> = +pub static LIBFUNC_PROFILE: LazyLock>> = LazyLock::new(|| Mutex::new(HashMap::new())); #[derive(Default)] -pub struct ProfileImpl { - pub trace: Vec<(StatementIdx, u64)>, +pub struct ProfilerImpl { + /// The samples recorded by the profiler. A value of `u64::MAX` implies + /// that the delta time for a statement could not be gathered. + pub samples: Vec<(StatementIdx, u64)>, } -impl ProfileImpl { +impl ProfilerImpl { pub fn new() -> Self { - Self { trace: Vec::new() } + Self { + samples: Vec::new(), + } } // Push a profiler frame - pub extern "C" fn push_stmt(trace_id: u64, statement_idx: u64, tick_delta: u64) { + pub extern "C" fn push_stmt(profile_id: u64, statement_idx: u64, tick_delta: u64) { let mut profiler = LIBFUNC_PROFILE.lock().unwrap(); - let Some(profiler) = profiler.get_mut(&trace_id) else { + let Some(profiler) = profiler.get_mut(&profile_id) else { eprintln!("Could not find libfunc profiler!"); return; }; profiler - .trace + .samples .push((StatementIdx(statement_idx as usize), tick_delta)); } - /// Process profiling results. - /// - /// Receives a closure with the flowing paramaters `(libfunc_id, (vec, extra_count))` to - /// process profiles information. - /// - /// `extra_count`: counter of libfunc calls whose execution time - /// hasn't been calculated for being invalid. - /// - pub fn get_profiles(&self, sierra_program: &Program) -> LibfuncProfiles { - let mut trace = HashMap::, u64)>::new(); + /// Returns the execution profile, grouped by libfunc + pub fn get_profile(&self, sierra_program: &Program) -> Profile { + let mut profile = HashMap::::new(); - for (statement_idx, tick_delta) in self.trace.iter() { + for (statement_idx, tick_delta) in self.samples.iter() { if let Statement::Invocation(invocation) = &sierra_program.statements[statement_idx.0] { - let (tick_deltas, extra_count) = - trace.entry(invocation.libfunc_id.clone()).or_default(); + let LibfuncProfileData { + deltas, + extra_counts, + } = profile.entry(invocation.libfunc_id.clone()).or_default(); // A tick_delta equal to u64::MAX implies it is invalid, so we don't take it // into account if *tick_delta != u64::MAX { - tick_deltas.push(*tick_delta); + deltas.push(*tick_delta); } else { - *extra_count += 1; + *extra_counts += 1; } } } - trace + profile } } From 243f8744ca4e99796194ca6f2657f7a62725e8f7 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Thu, 12 Jun 2025 17:42:32 -0300 Subject: [PATCH 25/27] add documentation about time deltas' unit --- src/metadata/profiler.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 6c0494876..1b1511621 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -172,8 +172,10 @@ impl ProfilerMeta { /// Gets the current timestamp. /// /// The values returned are: - /// 1. Timestamp - /// 2. CPU's id core in which the program is running (only for x86 arch) + /// 1. Timestamp: CPU cycles since its reset. + /// 2. CPU's id core in which the execution is running (only for x86 arch). + /// In case of arm, 0 is always return as there's no way to know in which + /// CPU core the execution was run. /// /// We use the last value to ensure that both the initial and then end timestamp of /// a libfunc's execution where calculated by the same core. This is to avoid gathering @@ -229,8 +231,10 @@ impl ProfilerMeta { /// Gets the current timestamp. /// /// The values returned are: - /// 1. Timestamp - /// 2. CPU's id core in which the program is running (only for x86 arch) + /// 1. Timestamp: CPU cycles since its reset. + /// 2. CPU's id core in which the program is running (only for x86 arch). + /// In case of arm, 0 is always return as there's no way to know in which + /// CPU core the execution was run. /// /// We use the last value to ensure that both the initial and then end timestamp of /// a libfunc's execution where calculated by the same core. This is to avoid gathering @@ -336,6 +340,7 @@ type Profile = HashMap; #[derive(Default)] pub struct LibfuncProfileData { /// A vector of execution times, for each time the libfunc was executed. + /// It expreses the number of CPU cycles completed during the execution. pub deltas: Vec, /// If the time delta for a particular execution could not be gathered, /// we just increase `extra_counts` by 1. From f6f362e39d71b33b4b6f49812b58c108d67ba4af Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Fri, 13 Jun 2025 09:58:20 -0300 Subject: [PATCH 26/27] fix documentation in general --- src/bin/cairo-native-run.rs | 45 +++++++++++++++++++------------------ src/compiler.rs | 4 ++-- src/metadata/profiler.rs | 28 ++++++++++------------- 3 files changed, 37 insertions(+), 40 deletions(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index a2bc8b0a5..17ba951ee 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -236,8 +236,8 @@ fn main() -> anyhow::Result<()> { if let Some(profiler_output_path) = args.profiler_output { let mut output = File::create(profiler_output_path)?; - let raw_profiles = profile.get_profile(&sierra_program); - let mut processed_profiles = process_profiles(raw_profiles); + let raw_profile = profile.get_profile(&sierra_program); + let mut processed_profile = process_profiles(raw_profiles); processed_profiles.sort_by_key(|LibfuncProfileSummary { libfunc_idx, .. }| { sierra_program @@ -287,13 +287,13 @@ fn main() -> anyhow::Result<()> { } #[cfg(feature = "with-libfunc-profiling")] -pub struct LibfuncProfileSummary { - pub libfunc_idx: ConcreteLibfuncId, - pub samples: u64, - pub total_time: u64, - pub average_time: f64, - pub std_deviation: f64, - pub quartiles: [u64; 5], +struct LibfuncProfileSummary { + pub libfunc_idx: Option, + pub samples: Option, + pub total_time: Option, + pub average_time: Option, + pub std_deviation: Option, + pub quartiles: Option<[u64; 5]>, } #[cfg(feature = "with-libfunc-profiling")] @@ -313,12 +313,12 @@ fn process_profiles( // if no deltas were registered, we only return the libfunc's calls amount if deltas.is_empty() { return LibfuncProfileSummary { - libfunc_idx, - samples: extra_counts, - total_time: 0, - average_time: 0.0, - std_deviation: 0.0, - quartiles: [0; 5], + libfunc_idx: Some(libfunc_idx), + samples: Some(extra_counts), + total_time: Some(0), + average_time: Some(0.0), + std_deviation: Some(0.0), + quartiles: Some([0; 5]), }; } @@ -361,13 +361,14 @@ fn process_profiles( }; LibfuncProfileSummary { - libfunc_idx, - samples: deltas.len() as u64 + extra_counts, - total_time: deltas.iter().sum::() - + (extra_counts as f64 * average).round() as u64, - average_time: average, - std_deviation: std_dev, - quartiles, + libfunc_idx: Some(libfunc_idx), + samples: Some(deltas.len() as u64 + extra_counts), + total_time: Some( + deltas.iter().sum::() + (extra_counts as f64 * average).round() as u64, + ), + average_time: Some(average), + std_deviation: Some(std_dev), + quartiles: Some(quartiles), } }, ) diff --git a/src/compiler.rs b/src/compiler.rs index 539805efa..cecf22f5f 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -624,8 +624,8 @@ fn compile_func( profiler: match libfunc { CoreConcreteLibfunc::FunctionCall(_) => { // Tail-recursive function calls are broken beacuse a stack of timestamps is required, - // which would invalidate tail recursion. Also since each libfunc is measured individually, - // doesn't make sense to take function calls into account, therefore it's ignored on purpose. + // which would invalidate tail recursion. Also, since each libfunc is measured individually, + // it doesn't make sense to take function calls into account, therefore it's ignored on purpose. None } _ => match metadata.remove::() diff --git a/src/metadata/profiler.rs b/src/metadata/profiler.rs index 1b1511621..c2f1f487c 100644 --- a/src/metadata/profiler.rs +++ b/src/metadata/profiler.rs @@ -2,7 +2,8 @@ //! The libfunc profiling feature is used to generate information about every libfunc executed in a sierra program. //! //! When this feature is used, the compiler will call the important methods: -//! 1. `measure_timestamp`: called before every libfunc execution. +//! +//! 1. `measure_timestamp`: called before every libfunc execution. //! //! 2. `push_frame`: called before every branching operation. This method will also call `measure_timestamp`. This, //! with the timestamp calculated before the execution, will allow to measure each statement's execution time. @@ -16,12 +17,12 @@ //! profiles for multiple executions. To do so, we need two important elements, which must be set before every contract //! execution: //! -//! 1. A golbal static hashmap to map every profile ID to its respective profiler. See `LIBFUNC_PROFILE`. +//! 1. A global static hashmap to map every profile ID to its respective profiler. See `LIBFUNC_PROFILE`. //! //! 2. A counter to track the ID of the current profiler, which gets updated every time we switch to another -//! contract. Since a contract can call other contract's, we need a way of restoring the counter after every execution. +//! contract. Since a contract can call other contracts, we need a way of restoring the counter after every execution. //! -//! See cairo-native-run` for an example on how to do it. +//! See `cairo-native-run` for an example on how to do it. use crate::{ error::{Error, Result}, @@ -174,11 +175,11 @@ impl ProfilerMeta { /// The values returned are: /// 1. Timestamp: CPU cycles since its reset. /// 2. CPU's id core in which the execution is running (only for x86 arch). - /// In case of arm, 0 is always return as there's no way to know in which + /// In case of arm, 0 is always returned as there's no way to know in which /// CPU core the execution was run. /// - /// We use the last value to ensure that both the initial and then end timestamp of - /// a libfunc's execution where calculated by the same core. This is to avoid gathering + /// We use the last value to ensure that both the initial and the end timestamp of + /// a libfunc's execution were calculated by the same core. This is to avoid gathering /// invalid data #[cfg(target_arch = "x86_64")] pub fn measure_timestamp<'c, 'a>( @@ -233,11 +234,11 @@ impl ProfilerMeta { /// The values returned are: /// 1. Timestamp: CPU cycles since its reset. /// 2. CPU's id core in which the program is running (only for x86 arch). - /// In case of arm, 0 is always return as there's no way to know in which + /// In case of arm, 0 is always returned as there's no way to know in which /// CPU core the execution was run. /// - /// We use the last value to ensure that both the initial and then end timestamp of - /// a libfunc's execution where calculated by the same core. This is to avoid gathering + /// We use the last value to ensure that both the initial and the end timestamp of + /// a libfunc's execution were calculated by the same core. This is to avoid gathering /// invalid data #[cfg(target_arch = "aarch64")] pub fn measure_timestamp<'c, 'a>( @@ -326,14 +327,9 @@ impl ProfilerMeta { } } -/// Represents a libfunc's profile. A libfunc profile maps libfuncs id -/// to a tuple with a vector of deltas (*1) and extra counts (*2). -/// *1 Each delta refers to the execution time of that libfunc call -/// *2 `extra_count` is a count of libfunc calls whose execution time -/// couldn't be calculated. /// Represents the entire profile of the execution. /// -///It maps the libfunc ID to a libfunc profile. +/// It maps the libfunc ID to a libfunc profile. type Profile = HashMap; /// Represents the profile data for a particular libfunc. From 11bd05a211d7efa6e4db25c3708fb58aa1833b49 Mon Sep 17 00:00:00 2001 From: FrancoGiachetta Date: Fri, 13 Jun 2025 16:03:24 -0300 Subject: [PATCH 27/27] forgot to use None when no deltas were calculated --- src/bin/cairo-native-run.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bin/cairo-native-run.rs b/src/bin/cairo-native-run.rs index 54123edfc..ce40390b2 100644 --- a/src/bin/cairo-native-run.rs +++ b/src/bin/cairo-native-run.rs @@ -328,10 +328,10 @@ fn process_profile( return LibfuncProfileSummary { libfunc_idx, samples: extra_counts, - total_time: Some(0), - average_time: Some(0.0), - std_deviation: Some(0.0), - quartiles: Some([0; 5]), + total_time: None, + average_time: None, + std_deviation: None, + quartiles: None, }; }