From 8c0d9114c556026fd963572d93c8a4a10ff4ee1f Mon Sep 17 00:00:00 2001 From: Koby Date: Fri, 3 Nov 2023 15:21:07 +0100 Subject: [PATCH 01/11] feat: add profile info print out --- compiler/noirc_errors/src/debug_info.rs | 18 +++++++++ tooling/nargo/src/artifacts/debug.rs | 12 +++++- tooling/nargo_cli/src/cli/info_cmd.rs | 50 ++++++++++++++++++++++++- 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index 946841c279b..4ae75260c1f 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -4,6 +4,8 @@ use acvm::compiler::AcirTransformationMap; use serde_with::serde_as; use serde_with::DisplayFromStr; use std::collections::BTreeMap; +use std::collections::HashMap; +use std::collections::HashSet; use std::mem; use crate::Location; @@ -42,4 +44,20 @@ impl DebugInfo { pub fn opcode_location(&self, loc: &OpcodeLocation) -> Option> { self.locations.get(loc).cloned() } + + pub fn count_span_opcodes(&self) -> HashMap<&Location, usize> { + let mut accumulator: HashMap<&Location, HashSet<&OpcodeLocation>> = HashMap::new(); + + for (opcode_location, locations) in self.locations.iter() { + for location in locations.iter() { + let what = accumulator.entry(location).or_insert(HashSet::new()); + what.insert(opcode_location); + } + } + + let counted_opcodes: HashMap<&Location, usize> = + accumulator.iter().map(|(location, opcodes)| (*location, opcodes.len())).collect(); + + counted_opcodes + } } diff --git a/tooling/nargo/src/artifacts/debug.rs b/tooling/nargo/src/artifacts/debug.rs index 19d8b88e641..352cb648523 100644 --- a/tooling/nargo/src/artifacts/debug.rs +++ b/tooling/nargo/src/artifacts/debug.rs @@ -1,5 +1,5 @@ use codespan_reporting::files::{Error, Files, SimpleFile}; -use noirc_driver::DebugFile; +use noirc_driver::{CompiledProgram, DebugFile}; use noirc_errors::{debug_info::DebugInfo, Location}; use noirc_evaluator::errors::SsaReport; use serde::{Deserialize, Serialize}; @@ -96,6 +96,16 @@ impl DebugArtifact { } } +impl From for DebugArtifact { + fn from(compiled_program: CompiledProgram) -> Self { + DebugArtifact { + debug_symbols: vec![compiled_program.debug], + file_map: compiled_program.file_map, + warnings: compiled_program.warnings, + } + } +} + impl<'a> Files<'a> for DebugArtifact { type FileId = FileId; type Name = PathString; diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index de0c63c3ab3..10df6601bf1 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -1,12 +1,15 @@ +use std::collections::HashMap; + use acvm::Language; use backend_interface::BackendError; use clap::Args; use iter_extended::vecmap; -use nargo::package::Package; +use nargo::{artifacts::debug::DebugArtifact, package::Package}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{ CompileOptions, CompiledContract, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, }; +use noirc_errors::Location; use noirc_frontend::graph::CrateName; use prettytable::{row, table, Row}; use rayon::prelude::*; @@ -36,6 +39,9 @@ pub(crate) struct InfoCommand { #[clap(long, hide = true)] json: bool, + #[clap(long, hide = true)] + profile_info: bool, + #[clap(flatten)] compile_options: CompileOptions, } @@ -71,6 +77,14 @@ pub(crate) fn run( &args.compile_options, )?; + if args.profile_info { + for compiled_program in &compiled_programs { + let span_opcodes = compiled_program.debug.count_span_opcodes(); + let debug_artifact: DebugArtifact = compiled_program.clone().into(); + print_span_opcodes(&span_opcodes, debug_artifact); + } + } + let program_info = binary_packages .into_par_iter() .zip(compiled_programs) @@ -121,6 +135,40 @@ pub(crate) fn run( Ok(()) } +fn print_span_opcodes(span_opcodes_map: &HashMap<&Location, usize>, debug_artifact: DebugArtifact) { + let mut pairs: Vec<(&&Location, &usize)> = span_opcodes_map.iter().collect(); + + pairs.sort_by(|a, b| a.1.cmp(b.1)); + + for (location, opcodes_len) in pairs { + let debug_file = debug_artifact.file_map.get(&location.file).unwrap(); + + let start_byte = byte_index(&debug_file.source, location.span.start() + 1); + let end_byte = byte_index(&debug_file.source, location.span.end() + 1); + let range = start_byte..end_byte; + let span_content = &debug_file.source[range]; + let line = debug_artifact.location_line_index(**location).unwrap(); + println!("File: {}", debug_file.path.to_str().unwrap()); + println!("Ln. {}: {} ({} opcode|s)", line, span_content, opcodes_len); + } +} +fn byte_index(string: &str, index: u32) -> usize { + let mut byte_index = 0; + let mut char_index = 0; + + #[allow(clippy::explicit_counter_loop)] + for (byte_offset, _) in string.char_indices() { + if char_index == index { + return byte_index; + } + + byte_index = byte_offset; + char_index += 1; + } + + byte_index +} + #[derive(Debug, Default, Serialize)] struct InfoReport { programs: Vec, From 5a56b6b8b21b92ece46caf6abe7f09cdd5474773 Mon Sep 17 00:00:00 2001 From: Koby Date: Fri, 3 Nov 2023 16:48:21 +0100 Subject: [PATCH 02/11] feat: add contracts profile info print --- tooling/nargo/src/artifacts/debug.rs | 18 +++++++++++++++++- tooling/nargo_cli/src/cli/info_cmd.rs | 25 +++++++++++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/tooling/nargo/src/artifacts/debug.rs b/tooling/nargo/src/artifacts/debug.rs index 352cb648523..edc6530bac8 100644 --- a/tooling/nargo/src/artifacts/debug.rs +++ b/tooling/nargo/src/artifacts/debug.rs @@ -1,5 +1,5 @@ use codespan_reporting::files::{Error, Files, SimpleFile}; -use noirc_driver::{CompiledProgram, DebugFile}; +use noirc_driver::{CompiledContract, CompiledProgram, DebugFile}; use noirc_errors::{debug_info::DebugInfo, Location}; use noirc_evaluator::errors::SsaReport; use serde::{Deserialize, Serialize}; @@ -106,6 +106,22 @@ impl From for DebugArtifact { } } +impl From<&CompiledContract> for DebugArtifact { + fn from(compiled_artifact: &CompiledContract) -> Self { + let all_functions_debug: Vec = compiled_artifact + .functions + .iter() + .map(|contract_function| contract_function.debug.clone()) + .collect(); + + DebugArtifact { + debug_symbols: all_functions_debug, + file_map: compiled_artifact.file_map.clone(), + warnings: Vec::new(), + } + } +} + impl<'a> Files<'a> for DebugArtifact { type FileId = FileId; type Name = PathString; diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index 10df6601bf1..fda2577aba9 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -81,7 +81,16 @@ pub(crate) fn run( for compiled_program in &compiled_programs { let span_opcodes = compiled_program.debug.count_span_opcodes(); let debug_artifact: DebugArtifact = compiled_program.clone().into(); - print_span_opcodes(&span_opcodes, debug_artifact); + print_span_opcodes(&span_opcodes, &debug_artifact); + } + + for compiled_contract in &compiled_contracts { + let debug_artifact: DebugArtifact = compiled_contract.clone().into(); + let functions = &compiled_contract.functions; + for contract_function in functions { + let span_opcodes = contract_function.debug.count_span_opcodes(); + print_span_opcodes(&span_opcodes, &debug_artifact); + } } } @@ -135,7 +144,10 @@ pub(crate) fn run( Ok(()) } -fn print_span_opcodes(span_opcodes_map: &HashMap<&Location, usize>, debug_artifact: DebugArtifact) { +fn print_span_opcodes( + span_opcodes_map: &HashMap<&Location, usize>, + debug_artifact: &DebugArtifact, +) { let mut pairs: Vec<(&&Location, &usize)> = span_opcodes_map.iter().collect(); pairs.sort_by(|a, b| a.1.cmp(b.1)); @@ -148,8 +160,13 @@ fn print_span_opcodes(span_opcodes_map: &HashMap<&Location, usize>, debug_artifa let range = start_byte..end_byte; let span_content = &debug_file.source[range]; let line = debug_artifact.location_line_index(**location).unwrap(); - println!("File: {}", debug_file.path.to_str().unwrap()); - println!("Ln. {}: {} ({} opcode|s)", line, span_content, opcodes_len); + println!( + "Ln. {}: {} ({} opcode|s) in file: {}", + line, + span_content, + opcodes_len, + debug_file.path.to_str().unwrap() + ); } } fn byte_index(string: &str, index: u32) -> usize { From b047c58ff23da61653c6e59e1e5bce8cf91a3d8a Mon Sep 17 00:00:00 2001 From: Koby Date: Fri, 3 Nov 2023 18:07:18 +0100 Subject: [PATCH 03/11] chore: use proper collection --- compiler/noirc_errors/src/debug_info.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index 4ae75260c1f..d044f0d0b2d 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -5,7 +5,6 @@ use serde_with::serde_as; use serde_with::DisplayFromStr; use std::collections::BTreeMap; use std::collections::HashMap; -use std::collections::HashSet; use std::mem; use crate::Location; @@ -46,12 +45,12 @@ impl DebugInfo { } pub fn count_span_opcodes(&self) -> HashMap<&Location, usize> { - let mut accumulator: HashMap<&Location, HashSet<&OpcodeLocation>> = HashMap::new(); + let mut accumulator: HashMap<&Location, Vec<&OpcodeLocation>> = HashMap::new(); for (opcode_location, locations) in self.locations.iter() { for location in locations.iter() { - let what = accumulator.entry(location).or_insert(HashSet::new()); - what.insert(opcode_location); + let opcodes = accumulator.entry(location).or_insert(Vec::new()); + opcodes.push(opcode_location); } } From 5298fb610dabebbfaafa034a4355e6077220f575 Mon Sep 17 00:00:00 2001 From: Koby Date: Sun, 5 Nov 2023 11:44:47 +0100 Subject: [PATCH 04/11] fix: separation of acir and brillig codes --- compiler/noirc_errors/src/debug_info.rs | 30 ++++++++++++++++++++++--- tooling/nargo_cli/src/cli/info_cmd.rs | 17 ++++++++------ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index d044f0d0b2d..c94008af6e2 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -20,6 +20,11 @@ pub struct DebugInfo { pub locations: BTreeMap>, } +pub struct OpCodesCount { + pub acir_size: usize, + pub brillig_size: usize, +} + impl DebugInfo { pub fn new(locations: BTreeMap>) -> Self { DebugInfo { locations } @@ -44,7 +49,7 @@ impl DebugInfo { self.locations.get(loc).cloned() } - pub fn count_span_opcodes(&self) -> HashMap<&Location, usize> { + pub fn count_span_opcodes(&self) -> HashMap<&Location, OpCodesCount> { let mut accumulator: HashMap<&Location, Vec<&OpcodeLocation>> = HashMap::new(); for (opcode_location, locations) in self.locations.iter() { @@ -54,8 +59,27 @@ impl DebugInfo { } } - let counted_opcodes: HashMap<&Location, usize> = - accumulator.iter().map(|(location, opcodes)| (*location, opcodes.len())).collect(); + let counted_opcodes = accumulator + .iter() + .map(|(location, opcodes)| { + let acir_opcodes: Vec<_> = opcodes + .into_iter() + .filter(|opcode_location| matches!(opcode_location, OpcodeLocation::Acir(_))) + .collect(); + let brillig_opcodes: Vec<_> = opcodes + .into_iter() + .filter(|opcode_location| { + matches!(opcode_location, OpcodeLocation::Brillig { .. }) + }) + .collect(); + // let (acir_opcodes, brillig_opcodes): (Vec, Vec) = opcodes.iter().partition(|opc| matches!(opc, OpcodeLocation::Acir(_))); + let opcodes_count = OpCodesCount { + acir_size: acir_opcodes.len(), + brillig_size: brillig_opcodes.len(), + }; + (*location, opcodes_count) + }) + .collect(); counted_opcodes } diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index fda2577aba9..a8e5db2894b 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -9,7 +9,7 @@ use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelec use noirc_driver::{ CompileOptions, CompiledContract, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, }; -use noirc_errors::Location; +use noirc_errors::{debug_info::OpCodesCount, Location}; use noirc_frontend::graph::CrateName; use prettytable::{row, table, Row}; use rayon::prelude::*; @@ -145,14 +145,16 @@ pub(crate) fn run( } fn print_span_opcodes( - span_opcodes_map: &HashMap<&Location, usize>, + span_opcodes_map: &HashMap<&Location, OpCodesCount>, debug_artifact: &DebugArtifact, ) { - let mut pairs: Vec<(&&Location, &usize)> = span_opcodes_map.iter().collect(); + let mut pairs: Vec<(&&Location, &OpCodesCount)> = span_opcodes_map.iter().collect(); - pairs.sort_by(|a, b| a.1.cmp(b.1)); + pairs.sort_by(|a, b| { + a.1.acir_size.cmp(&b.1.acir_size).then_with(|| a.1.brillig_size.cmp(&b.1.brillig_size)) + }); - for (location, opcodes_len) in pairs { + for (location, opcodes_count) in pairs { let debug_file = debug_artifact.file_map.get(&location.file).unwrap(); let start_byte = byte_index(&debug_file.source, location.span.start() + 1); @@ -161,10 +163,11 @@ fn print_span_opcodes( let span_content = &debug_file.source[range]; let line = debug_artifact.location_line_index(**location).unwrap(); println!( - "Ln. {}: {} ({} opcode|s) in file: {}", + "Ln. {}: {} (ACIR:{}, Brillig:{} opcode|s) in file: {}", line, span_content, - opcodes_len, + opcodes_count.acir_size, + opcodes_count.brillig_size, debug_file.path.to_str().unwrap() ); } From 8be5b8d220dcd5e05c3b301c0ca20ba4423789c9 Mon Sep 17 00:00:00 2001 From: Koby Date: Mon, 6 Nov 2023 11:35:10 +0100 Subject: [PATCH 05/11] chore: address clippy --- compiler/noirc_errors/src/debug_info.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index c94008af6e2..bb9a53ff97c 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -63,11 +63,11 @@ impl DebugInfo { .iter() .map(|(location, opcodes)| { let acir_opcodes: Vec<_> = opcodes - .into_iter() + .iter() .filter(|opcode_location| matches!(opcode_location, OpcodeLocation::Acir(_))) .collect(); let brillig_opcodes: Vec<_> = opcodes - .into_iter() + .iter() .filter(|opcode_location| { matches!(opcode_location, OpcodeLocation::Brillig { .. }) }) From d4f8c5f11134d1eb64f9ef93c4166b7a7c422688 Mon Sep 17 00:00:00 2001 From: Koby Date: Tue, 7 Nov 2023 10:42:29 +0100 Subject: [PATCH 06/11] chore: drop leftover comment --- compiler/noirc_errors/src/debug_info.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index bb9a53ff97c..5a5fe9bc6dd 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -72,7 +72,6 @@ impl DebugInfo { matches!(opcode_location, OpcodeLocation::Brillig { .. }) }) .collect(); - // let (acir_opcodes, brillig_opcodes): (Vec, Vec) = opcodes.iter().partition(|opc| matches!(opc, OpcodeLocation::Acir(_))); let opcodes_count = OpCodesCount { acir_size: acir_opcodes.len(), brillig_size: brillig_opcodes.len(), From 4a73c372c30faa1f555d3b6f9082b04c965f4546 Mon Sep 17 00:00:00 2001 From: Koby Date: Tue, 7 Nov 2023 10:48:27 +0100 Subject: [PATCH 07/11] chore: add comment explaining struct purpose --- compiler/noirc_errors/src/debug_info.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index 5a5fe9bc6dd..a4092ec4a97 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -20,6 +20,8 @@ pub struct DebugInfo { pub locations: BTreeMap>, } +/// Holds OpCodes Counts for Acir and Brillig Opcodes +/// To be printed with `nargo info --profile-info` pub struct OpCodesCount { pub acir_size: usize, pub brillig_size: usize, From ddcf95391a3923caf5ede4c0f871dd4dc592792d Mon Sep 17 00:00:00 2001 From: Koby Date: Tue, 7 Nov 2023 10:53:09 +0100 Subject: [PATCH 08/11] chore: include missed warnings --- tooling/nargo/src/artifacts/debug.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling/nargo/src/artifacts/debug.rs b/tooling/nargo/src/artifacts/debug.rs index edc6530bac8..40acc7db8f8 100644 --- a/tooling/nargo/src/artifacts/debug.rs +++ b/tooling/nargo/src/artifacts/debug.rs @@ -117,7 +117,7 @@ impl From<&CompiledContract> for DebugArtifact { DebugArtifact { debug_symbols: all_functions_debug, file_map: compiled_artifact.file_map.clone(), - warnings: Vec::new(), + warnings: compiled_artifact.warnings.clone(), } } } From 851b21ab44498a38ec364d88094cd7a4d1e18f6a Mon Sep 17 00:00:00 2001 From: Koby Date: Tue, 7 Nov 2023 11:28:25 +0100 Subject: [PATCH 09/11] fix: line indexes off by 1 --- tooling/nargo_cli/src/cli/info_cmd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index a8e5db2894b..b429799f210 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -161,7 +161,7 @@ fn print_span_opcodes( let end_byte = byte_index(&debug_file.source, location.span.end() + 1); let range = start_byte..end_byte; let span_content = &debug_file.source[range]; - let line = debug_artifact.location_line_index(**location).unwrap(); + let line = debug_artifact.location_line_index(**location).unwrap() + 1; println!( "Ln. {}: {} (ACIR:{}, Brillig:{} opcode|s) in file: {}", line, From 053fa94eb277857b0c594a57e6d12eb9e30e80e6 Mon Sep 17 00:00:00 2001 From: Koby Date: Tue, 7 Nov 2023 13:12:04 +0100 Subject: [PATCH 10/11] chore: add print fn comment --- tooling/nargo_cli/src/cli/info_cmd.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index b429799f210..b9e73772be6 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -144,6 +144,10 @@ pub(crate) fn run( Ok(()) } +/// Provides profiling information on +/// +/// Number of OpCodes in relation to Noir source file +/// and line number information fn print_span_opcodes( span_opcodes_map: &HashMap<&Location, OpCodesCount>, debug_artifact: &DebugArtifact, From b31dfd820c244025fd3d836e2c7ecb0f97afb8c0 Mon Sep 17 00:00:00 2001 From: Koby Date: Tue, 7 Nov 2023 13:27:47 +0100 Subject: [PATCH 11/11] chore: fmt fix --- tooling/nargo_cli/src/cli/info_cmd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index b9e73772be6..665eb2ca256 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -144,8 +144,8 @@ pub(crate) fn run( Ok(()) } -/// Provides profiling information on -/// +/// Provides profiling information on +/// /// Number of OpCodes in relation to Noir source file /// and line number information fn print_span_opcodes(