Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tooling/profiler/src/cli/execution_flamegraph_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fn run_with_generator(
&debug_artifact,
artifact_path.to_str().unwrap(),
"main",
&Path::new(&output_path).join(Path::new(&format!("{}.svg", "main"))),
&Path::new(&output_path).join(Path::new(&format!("{}_brillig_trace.svg", "main"))),
)?;

Ok(())
Expand Down
29 changes: 17 additions & 12 deletions tooling/profiler/src/cli/gates_flamegraph_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,24 @@ fn run_with_provider<Provider: GatesProvider, Generator: FlamegraphGenerator>(
let backend_gates_response =
gates_provider.get_gates(artifact_path).context("Error querying backend for gates")?;

let function_names = program.names.clone();
let function_names = std::mem::take(&mut program.names);

let bytecode = std::mem::take(&mut program.bytecode);

let debug_artifact: DebugArtifact = program.into();

for (func_idx, ((func_gates, func_name), bytecode)) in backend_gates_response
.functions
.into_iter()
.zip(function_names)
.zip(bytecode.functions)
.enumerate()
let num_functions = bytecode.functions.len();
for (func_idx, (func_gates, circuit)) in
backend_gates_response.functions.into_iter().zip(bytecode.functions).enumerate()
{
// We can have repeated names if there are functions with the same name in different
// modules or functions that use generics. Thus, add the unique function index as a suffix.
let function_name = if num_functions > 1 {
format!("{}_{}", function_names[func_idx].as_str(), func_idx)
} else {
function_names[func_idx].to_owned()
};

println!(
"Opcode count: {}, Total gates by opcodes: {}, Circuit size: {}",
func_gates.acir_opcodes,
Expand All @@ -89,7 +94,7 @@ fn run_with_provider<Provider: GatesProvider, Generator: FlamegraphGenerator>(
let samples = func_gates
.gates_per_opcode
.into_iter()
.zip(bytecode.opcodes)
.zip(circuit.opcodes)
.enumerate()
.map(|(index, (gates, opcode))| CompilationSample {
opcode: Some(format_acir_opcode(&opcode)),
Expand All @@ -100,16 +105,16 @@ fn run_with_provider<Provider: GatesProvider, Generator: FlamegraphGenerator>(
.collect();

let output_filename = if let Some(output_filename) = &output_filename {
format!("{}::{}::gates.svg", output_filename, func_name)
format!("{}_{}_gates.svg", output_filename, function_name)
} else {
format!("{}::gates.svg", func_name)
format!("{}_gates.svg", function_name)
};
flamegraph_generator.generate_flamegraph(
samples,
&debug_artifact.debug_symbols[func_idx],
&debug_artifact,
artifact_path.to_str().unwrap(),
&func_name,
&function_name,
&Path::new(&output_path).join(Path::new(&output_filename)),
)?;
}
Expand Down Expand Up @@ -212,7 +217,7 @@ mod tests {
.expect("should run without errors");

// Check that the output file was written to
let output_file = temp_dir.path().join("test_filename::main::gates.svg");
let output_file = temp_dir.path().join("test_filename_main_gates.svg");
assert!(output_file.exists());
}
}
151 changes: 93 additions & 58 deletions tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,25 @@ fn run_with_generator<Generator: FlamegraphGenerator>(
let mut program =
read_program_from_file(artifact_path).context("Error reading program from file")?;

let function_names = program.names.clone();
let acir_names = std::mem::take(&mut program.names);
let brillig_names = std::mem::take(&mut program.brillig_names);

let bytecode = std::mem::take(&mut program.bytecode);

let debug_artifact: DebugArtifact = program.into();

for (func_idx, (func_name, bytecode)) in
function_names.into_iter().zip(bytecode.functions.iter()).enumerate()
{
println!("Opcode count for {}: {}", func_name, bytecode.opcodes.len());
for (func_idx, circuit) in bytecode.functions.iter().enumerate() {
// We can have repeated names if there are functions with the same name in different
// modules or functions that use generics. Thus, add the unique function index as a suffix.
let function_name = if bytecode.functions.len() > 1 {
format!("{}_{}", acir_names[func_idx].as_str(), func_idx)
} else {
acir_names[func_idx].to_owned()
};

let samples = bytecode
println!("Opcode count for {}: {}", function_name, circuit.opcodes.len());

let samples = circuit
.opcodes
.iter()
.enumerate()
Expand All @@ -73,51 +80,55 @@ fn run_with_generator<Generator: FlamegraphGenerator>(
&debug_artifact.debug_symbols[func_idx],
&debug_artifact,
artifact_path.to_str().unwrap(),
&func_name,
&Path::new(&output_path).join(Path::new(&format!("{}_acir_opcodes.svg", &func_name))),
&function_name,
&Path::new(&output_path)
.join(Path::new(&format!("{}_acir_opcodes.svg", &function_name))),
)?;
}

if !skip_brillig {
for (brillig_fn_index, brillig_bytecode) in
bytecode.unconstrained_functions.into_iter().enumerate()
{
let acir_location = locate_brillig_call(brillig_fn_index, &bytecode.functions);
let Some((acir_fn_index, acir_opcode_index)) = acir_location else {
continue;
};

println!(
"Opcode count for brillig_{}: {}",
brillig_fn_index,
brillig_bytecode.bytecode.len()
);

let samples = brillig_bytecode
.bytecode
.into_iter()
.enumerate()
.map(|(brillig_index, opcode)| CompilationSample {
opcode: Some(format_brillig_opcode(&opcode)),
call_stack: vec![OpcodeLocation::Brillig {
acir_index: acir_opcode_index,
brillig_index,
}],
count: 1,
brillig_function_id: Some(BrilligFunctionId(brillig_fn_index as u32)),
})
.collect();

flamegraph_generator.generate_flamegraph(
samples,
&debug_artifact.debug_symbols[acir_fn_index],
&debug_artifact,
artifact_path.to_str().unwrap(),
&format!("brillig_{}", brillig_fn_index),
&Path::new(&output_path)
.join(Path::new(&format!("{}_brillig_opcodes.svg", &brillig_fn_index))),
)?;
}
if skip_brillig {
return Ok(());
}

for (brillig_fn_index, brillig_bytecode) in
bytecode.unconstrained_functions.into_iter().enumerate()
{
let acir_location = locate_brillig_call(brillig_fn_index, &bytecode.functions);
let Some((acir_fn_index, acir_opcode_index)) = acir_location else {
continue;
};

// We can have repeated names if there are functions with the same name in different
// modules or functions that use generics. Thus, add the unique function index as a suffix.
let function_name =
format!("{}_{}", brillig_names[brillig_fn_index].as_str(), brillig_fn_index);

println!("Opcode count for {}_brillig: {}", function_name, brillig_bytecode.bytecode.len());

let samples = brillig_bytecode
.bytecode
.into_iter()
.enumerate()
.map(|(brillig_index, opcode)| CompilationSample {
opcode: Some(format_brillig_opcode(&opcode)),
call_stack: vec![OpcodeLocation::Brillig {
acir_index: acir_opcode_index,
brillig_index,
}],
count: 1,
brillig_function_id: Some(BrilligFunctionId(brillig_fn_index as u32)),
})
.collect();

flamegraph_generator.generate_flamegraph(
samples,
&debug_artifact.debug_symbols[acir_fn_index],
&debug_artifact,
artifact_path.to_str().unwrap(),
&function_name,
&Path::new(&output_path)
.join(Path::new(&format!("{}_brillig_opcodes.svg", function_name))),
)?;
}

Ok(())
Expand Down Expand Up @@ -215,25 +226,43 @@ mod tests {

let artifact_path = temp_dir.path().join("test.json");

let acir: Vec<Opcode<FieldElement>> = vec![Opcode::BrilligCall {
id: BrilligFunctionId(0),
inputs: vec![],
outputs: vec![],
predicate: None,
}];
let acir: Vec<Opcode<FieldElement>> = vec![
Opcode::BrilligCall {
id: BrilligFunctionId(0),
inputs: vec![],
outputs: vec![],
predicate: None,
},
Opcode::BrilligCall {
id: BrilligFunctionId(1),
inputs: vec![],
outputs: vec![],
predicate: None,
},
Opcode::BrilligCall {
id: BrilligFunctionId(2),
inputs: vec![],
outputs: vec![],
predicate: None,
},
];

let artifact = ProgramArtifact {
noir_version: "0.0.0".to_string(),
hash: 27,
abi: noirc_abi::Abi::default(),
bytecode: Program {
functions: vec![Circuit { opcodes: acir, ..Circuit::default() }],
unconstrained_functions: vec![BrilligBytecode::default()],
unconstrained_functions: vec![
BrilligBytecode::default(),
BrilligBytecode::default(),
BrilligBytecode::default(),
],
},
debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] },
file_map: BTreeMap::default(),
names: vec!["main".to_string()],
brillig_names: vec!["main".to_string()],
brillig_names: vec!["main".to_string(), "main".to_string(), "main_1".to_string()],
};

// Write the artifact to a file
Expand All @@ -245,11 +274,17 @@ mod tests {
super::run_with_generator(&artifact_path, &flamegraph_generator, temp_dir.path(), false)
.expect("should run without errors");

// Check that the output files ware written to
// Check that the output files were written
let output_file = temp_dir.path().join("main_acir_opcodes.svg");
assert!(output_file.exists());

let output_file = temp_dir.path().join("0_brillig_opcodes.svg");
let output_file = temp_dir.path().join("main_0_brillig_opcodes.svg");
assert!(output_file.exists());

let output_file = temp_dir.path().join("main_1_brillig_opcodes.svg");
assert!(output_file.exists());

let output_file = temp_dir.path().join("main_1_2_brillig_opcodes.svg");
assert!(output_file.exists());
}
}
2 changes: 1 addition & 1 deletion tooling/profiler/src/flamegraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl FlamegraphGenerator for InfernoFlamegraphGenerator {
let mut options = Options::default();
options.hash = true;
options.deterministic = true;
options.title = format!("{}-{}", artifact_name, function_name);
options.title = format!("Artifact: {}, Function: {}", artifact_name, function_name);
options.frame_height = 24;
options.color_diffusion = true;
options.min_width = 0.0;
Expand Down
Loading