@@ -8,6 +8,7 @@ use cairo_vm::cairo_run;
88use cairo_vm:: types:: errors:: program_errors:: ProgramError ;
99use cairo_vm:: types:: layout_name:: LayoutName ;
1010use cairo_vm:: vm:: errors:: cairo_run_errors:: CairoRunError ;
11+ use cairo_vm:: vm:: runners:: cairo_runner:: CairoRunner ;
1112use clap:: Parser ;
1213use stwo_cairo_adapter:: adapter:: adapt;
1314use stwo_cairo_adapter:: { ExecutionResources , ProverInput } ;
@@ -62,6 +63,42 @@ enum Error {
6263 Anyhow ( #[ from] anyhow:: Error ) ,
6364}
6465
66+ /// Calculate approximate heap memory usage for a Vec
67+ fn vec_heap_size < T > ( vec : & Vec < T > ) -> usize {
68+ vec. capacity ( ) * std:: mem:: size_of :: < T > ( )
69+ }
70+
71+ /// Calculate approximate heap memory usage for an Option<Vec<T>>
72+ fn option_vec_heap_size < T > ( opt_vec : & Option < Vec < T > > ) -> usize {
73+ opt_vec. as_ref ( ) . map ( |v| vec_heap_size ( v) ) . unwrap_or ( 0 )
74+ }
75+
76+ /// Estimate the total memory usage of CairoRunner by summing accessible components.
77+ /// This is an approximation and may not capture all memory.
78+ fn estimate_cairo_runner_total_size ( runner : & CairoRunner ) -> usize {
79+ let mut total = std:: mem:: size_of_val ( runner) ; // Stack size
80+
81+ // Add relocated_trace if present.
82+ total += option_vec_heap_size ( & runner. relocated_trace ) ;
83+
84+ // Add VM memory segments - this is the big one!
85+ // The memory is stored as a Vec of Option<Felt252> in segments.memory
86+ // We'll try to estimate based on segment sizes.
87+ for ( _segment_idx, size) in & runner. vm . segments . segment_sizes {
88+ // Each memory cell is roughly 32 bytes (Felt252) when Some, plus Option overhead.
89+ total += size * 40 ; // Rough estimate: 32 bytes + Option + padding
90+ }
91+
92+ // Add program data.
93+ let program = runner. get_program ( ) ;
94+ total += program. data_len ( ) * std:: mem:: size_of :: < cairo_vm:: types:: relocatable:: MaybeRelocatable > ( ) ;
95+
96+ // Add public_memory_offsets HashMap overhead (rough estimate).
97+ total += runner. vm . segments . public_memory_offsets . len ( ) * 64 ;
98+
99+ total
100+ }
101+
65102fn main ( ) -> ExitCode {
66103 run_binary ( run, "stwo_vm_runner" )
67104}
@@ -91,8 +128,46 @@ fn run() -> Result<ProverInput, Error> {
91128 } ;
92129
93130 let cairo_runner = cairo_run_program ( & program, program_input_contents, cairo_run_config) ?;
131+
132+ // Log total estimated memory (approximation).
133+ let estimated_total = estimate_cairo_runner_total_size ( & cairo_runner) ;
134+ log:: info!( "=== TOTAL ESTIMATED SIZE ===" ) ;
135+ log:: info!( "cairo_runner TOTAL (estimated): {} bytes ({} MB, {:.2} GB)" ,
136+ estimated_total,
137+ estimated_total / 1_048_576 ,
138+ estimated_total as f64 / 1_073_741_824.0 ) ;
139+
140+ // Log stack sizes (struct sizes).
141+ log:: info!( "=== Stack Sizes (struct metadata only) ===" ) ;
142+ log:: info!( "cairo_runner stack: {} bytes" , std:: mem:: size_of_val( & cairo_runner) ) ;
143+ log:: info!( "cairo_runner.vm stack: {} bytes" , std:: mem:: size_of_val( & cairo_runner. vm) ) ;
144+ log:: info!( "cairo_runner.get_program() stack: {} bytes" , std:: mem:: size_of_val( cairo_runner. get_program( ) ) ) ;
145+ log:: info!( "cairo_runner.exec_scopes stack: {} bytes" , std:: mem:: size_of_val( & cairo_runner. exec_scopes) ) ;
146+ log:: info!( "cairo_runner.relocated_trace stack: {} bytes" , std:: mem:: size_of_val( & cairo_runner. relocated_trace) ) ;
147+
148+ // Log heap sizes (actual allocated data).
149+ log:: info!( "=== Heap Sizes (actual memory consumption) ===" ) ;
150+ log:: info!( "cairo_runner.relocated_trace heap: {} bytes ({} MB)" ,
151+ option_vec_heap_size( & cairo_runner. relocated_trace) ,
152+ option_vec_heap_size( & cairo_runner. relocated_trace) / 1_048_576 ) ;
153+ log:: info!( "cairo_runner.vm.segments (estimated): {} segments" ,
154+ cairo_runner. vm. segments. segment_sizes. len( ) ) ;
155+
156+ // VM segments memory is complex, log the HashMap size.
157+ log:: info!( "cairo_runner.vm.segments.public_memory_offsets entries: {}" ,
158+ cairo_runner. vm. segments. public_memory_offsets. len( ) ) ;
159+
94160 let prover_input = adapt ( & cairo_runner) ?;
95161
162+ log:: info!( "=== After Adaptation ===" ) ;
163+ log:: info!( "prover_input stack: {} bytes" , std:: mem:: size_of_val( & prover_input) ) ;
164+ log:: info!( "prover_input.public_memory_addresses heap: {} bytes ({} MB)" ,
165+ vec_heap_size( & prover_input. public_memory_addresses) ,
166+ vec_heap_size( & prover_input. public_memory_addresses) / 1_048_576 ) ;
167+
168+ // Note: prover_input doesn't implement DeepSizeOf, so we can't get total size easily.
169+ // The memory component is the largest but is opaque to us here.
170+
96171 if let Some ( prover_input_path) = args. output_prover_input_path {
97172 std:: fs:: write ( prover_input_path, serde_json:: to_string ( & prover_input) ?) ?;
98173 }
0 commit comments