Skip to content

Commit

Permalink
chore(profiler): Docs on profiler command and more complete error rep…
Browse files Browse the repository at this point in the history
…orting (#7436)

Co-authored-by: Michael J Klein <[email protected]>
  • Loading branch information
vezenovm and michaeljklein authored Feb 20, 2025
1 parent 7a9c8c1 commit da364d8
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion tooling/profiler/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "noir_profiler"
description = "Profiler for noir circuits"
description = "Profiler for Noir circuits"
version.workspace = true
authors.workspace = true
edition.workspace = true
Expand Down Expand Up @@ -34,6 +34,7 @@ nargo.workspace = true
noirc_errors.workspace = true
noirc_abi.workspace = true
noirc_evaluator.workspace = true
thiserror.workspace = true

# Logs
tracing-subscriber.workspace = true
Expand Down
53 changes: 50 additions & 3 deletions tooling/profiler/src/cli/execution_flamegraph_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
use std::path::{Path, PathBuf};

use acir::circuit::Opcode;
use acir::circuit::OpcodeLocation;
use clap::Args;
use color_eyre::eyre::{self, Context};
use nargo::errors::try_to_diagnose_runtime_error;
use nargo::foreign_calls::DefaultForeignCallBuilder;
use nargo::PrintOutput;
use noirc_artifacts::program::ProgramArtifact;

use crate::errors::{report_error, CliError};
use crate::flamegraph::{BrilligExecutionSample, FlamegraphGenerator, InfernoFlamegraphGenerator};
use crate::fs::{read_inputs_from_file, read_program_from_file};
use crate::opcode_formatter::format_brillig_opcode;
use bn254_blackbox_solver::Bn254BlackBoxSolver;
use noirc_abi::input_parser::Format;
use noirc_artifacts::debug::DebugArtifact;

/// Generates a flamegraph mapping unconstrained Noir execution to source code.
#[derive(Debug, Clone, Args)]
pub(crate) struct ExecutionFlamegraphCommand {
/// The path to the artifact JSON file
Expand Down Expand Up @@ -54,17 +59,40 @@ fn run_with_generator(
let program =
read_program_from_file(artifact_path).context("Error reading program from file")?;

ensure_brillig_entry_point(&program)?;

let (inputs_map, _) = read_inputs_from_file(prover_toml_path, Format::Toml, &program.abi)?;

let initial_witness = program.abi.encode(&inputs_map, None)?;

println!("Executing");
let (_, mut profiling_samples) = nargo::ops::execute_program_with_profiling(
println!("Executing...");

let solved_witness_stack_err = nargo::ops::execute_program_with_profiling(
&program.bytecode,
initial_witness,
&Bn254BlackBoxSolver(pedantic_solving),
&mut DefaultForeignCallBuilder::default().with_output(PrintOutput::Stdout).build(),
)?;
);
let mut profiling_samples = match solved_witness_stack_err {
Ok((_, profiling_samples)) => profiling_samples,
Err(err) => {
let debug_artifact = DebugArtifact {
debug_symbols: program.debug_symbols.debug_infos.clone(),
file_map: program.file_map.clone(),
};

if let Some(diagnostic) = try_to_diagnose_runtime_error(
&err,
&program.abi,
&program.debug_symbols.debug_infos,
) {
diagnostic.report(&debug_artifact, false);
}

return Err(CliError::Generic.into());
}
};

println!("Executed");

println!("Collecting {} samples", profiling_samples.len());
Expand Down Expand Up @@ -104,3 +132,22 @@ fn run_with_generator(

Ok(())
}

fn ensure_brillig_entry_point(artifact: &ProgramArtifact) -> Result<(), CliError> {
let err_msg = "Command only supports fully unconstrained Noir programs e.g. `unconstrained fn main() { .. }".to_owned();
let program = &artifact.bytecode;
if program.functions.len() != 1 || program.unconstrained_functions.len() != 1 {
return report_error(err_msg);
}

let main_function = &program.functions[0];
let Opcode::BrilligCall { id, .. } = main_function.opcodes[0] else {
return report_error(err_msg);
};

if id.as_usize() != 0 {
return report_error(err_msg);
}

Ok(())
}
4 changes: 3 additions & 1 deletion tooling/profiler/src/cli/gates_flamegraph_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ use crate::fs::read_program_from_file;
use crate::gates_provider::{BackendGatesProvider, GatesProvider};
use crate::opcode_formatter::format_acir_opcode;

/// Generates a flamegraph mapping backend opcodes to their associated locations in the source code.
#[derive(Debug, Clone, Args)]
pub(crate) struct GatesFlamegraphCommand {
/// The path to the artifact JSON file
#[clap(long, short)]
artifact_path: String,

/// Path to the noir backend binary
/// Path to the Noir backend binary
#[clap(long, short)]
backend_path: String,

/// Command to get a gates report from the backend. Defaults to "gates"
#[clap(long, short = 'g', default_value = "gates")]
backend_gates_command: String,

/// Optional arguments for the backend gates command
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
backend_extra_args: Vec<String>,

Expand Down
4 changes: 3 additions & 1 deletion tooling/profiler/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,7 @@ pub(crate) fn start_cli() -> eyre::Result<()> {
ProfilerCommand::Gates(args) => gates_flamegraph_cmd::run(args),
ProfilerCommand::Opcodes(args) => opcodes_flamegraph_cmd::run(args),
ProfilerCommand::ExecutionOpcodes(args) => execution_flamegraph_cmd::run(args),
}
}?;

Ok(())
}
1 change: 1 addition & 0 deletions tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::flamegraph::{CompilationSample, FlamegraphGenerator, InfernoFlamegrap
use crate::fs::read_program_from_file;
use crate::opcode_formatter::{format_acir_opcode, format_brillig_opcode};

/// Generates a flamegraph mapping ACIR opcodes to their associated locations in the source code.
#[derive(Debug, Clone, Args)]
pub(crate) struct OpcodesFlamegraphCommand {
/// The path to the artifact JSON file
Expand Down
16 changes: 16 additions & 0 deletions tooling/profiler/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use fm::FileMap;
use noirc_errors::{CustomDiagnostic, Span};
use thiserror::Error;

#[derive(Debug, Error)]
pub(crate) enum CliError {
#[error("Failed to run profiler command")]
Generic,
}

/// Report an error from the CLI that is not reliant on a stack trace.
pub(crate) fn report_error(message: String) -> Result<(), CliError> {
let error = CustomDiagnostic::simple_error(message.clone(), String::new(), Span::default());
noirc_errors::reporter::report(&FileMap::default(), &error, None, false);
Err(CliError::Generic)
}
3 changes: 2 additions & 1 deletion tooling/profiler/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))]

mod cli;
mod errors;
mod flamegraph;
mod fs;
mod gates_provider;
Expand Down Expand Up @@ -33,7 +34,7 @@ fn main() {
}

if let Err(report) = cli::start_cli() {
eprintln!("{report:?}");
eprintln!("{report}");
std::process::exit(1);
}
}

1 comment on commit da364d8

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'Test Suite Duration'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.

Benchmark suite Current: da364d8 Previous: 7a9c8c1 Ratio
AztecProtocol_aztec-packages_noir-projects_noir-protocol-circuits_crates_reset-kernel-lib 11 s 9 s 1.22

This comment was automatically generated by workflow using github-action-benchmark.

CC: @TomAFrench

Please sign in to comment.