Skip to content

Commit

Permalink
feat: compile circuits and query circuit sizes in parallel for `nargo…
Browse files Browse the repository at this point in the history
… info` (#2665)
  • Loading branch information
TomAFrench authored Sep 13, 2023
1 parent c9b710f commit f173c05
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 85 deletions.
61 changes: 29 additions & 32 deletions tooling/nargo_cli/src/cli/compile_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,52 +63,62 @@ pub(crate) fn run(
let workspace = resolve_workspace_from_toml(&toml_path, selection)?;
let circuit_dir = workspace.target_directory_path();

let (np_language, is_opcode_supported) = backend.get_backend_info()?;

let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace
.members
.iter()
.into_iter()
.filter(|package| !package.is_library())
.cloned()
.partition(|package| package.is_binary());

let (compiled_programs, compiled_contracts) =
compile_workspace(backend, &binary_packages, &contract_packages, &args.compile_options)?;

// Save build artifacts to disk.
for (package, program) in binary_packages.into_iter().zip(compiled_programs) {
save_program(program, &package, &circuit_dir, args.output_debug);
}
for (package, contract) in contract_packages.into_iter().zip(compiled_contracts) {
save_contract(contract, &package, &circuit_dir, args.output_debug);
}

Ok(())
}

pub(super) fn compile_workspace(
backend: &Backend,
binary_packages: &[Package],
contract_packages: &[Package],
compile_options: &CompileOptions,
) -> Result<(Vec<CompiledProgram>, Vec<CompiledContract>), CliError> {
let (np_language, is_opcode_supported) = backend.get_backend_info()?;

// Compile all of the packages in parallel.
let program_results: Vec<(FileManager, CompilationResult<CompiledProgram>)> = binary_packages
.par_iter()
.map(|package| {
compile_program(package, &args.compile_options, np_language, &is_opcode_supported)
})
.map(|package| compile_program(package, compile_options, np_language, &is_opcode_supported))
.collect();
let contract_results: Vec<(FileManager, CompilationResult<CompiledContract>)> =
contract_packages
.par_iter()
.map(|package| {
compile_contract(package, &args.compile_options, np_language, &is_opcode_supported)
compile_contract(package, compile_options, np_language, &is_opcode_supported)
})
.collect();

// Report any warnings/errors which were encountered during compilation.
let compiled_programs: Vec<CompiledProgram> = program_results
.into_iter()
.map(|(file_manager, compilation_result)| {
report_errors(compilation_result, &file_manager, args.compile_options.deny_warnings)
report_errors(compilation_result, &file_manager, compile_options.deny_warnings)
})
.collect::<Result<_, _>>()?;
let compiled_contracts: Vec<CompiledContract> = contract_results
.into_iter()
.map(|(file_manager, compilation_result)| {
report_errors(compilation_result, &file_manager, args.compile_options.deny_warnings)
report_errors(compilation_result, &file_manager, compile_options.deny_warnings)
})
.collect::<Result<_, _>>()?;

// Save build artifacts to disk.
for (package, program) in binary_packages.into_iter().zip(compiled_programs) {
save_program(program, package, &circuit_dir, args.output_debug);
}
for (package, compiled_contract) in contract_packages.into_iter().zip(compiled_contracts) {
save_contract(compiled_contract, package, &circuit_dir, args.output_debug);
}

Ok(())
Ok((compiled_programs, compiled_contracts))
}

pub(crate) fn compile_bin_package(
Expand All @@ -129,19 +139,6 @@ pub(crate) fn compile_bin_package(
Ok(program)
}

pub(crate) fn compile_contract_package(
package: &Package,
compile_options: &CompileOptions,
np_language: Language,
is_opcode_supported: &impl Fn(&Opcode) -> bool,
) -> Result<CompiledContract, CliError> {
let (file_manager, compilation_result) =
compile_contract(package, compile_options, np_language, &is_opcode_supported);
let contract_and_debug_artifact =
report_errors(compilation_result, &file_manager, compile_options.deny_warnings)?;
Ok(contract_and_debug_artifact)
}

fn compile_program(
package: &Package,
compile_options: &CompileOptions,
Expand Down
96 changes: 43 additions & 53 deletions tooling/nargo_cli/src/cli/info_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
use acvm::acir::circuit::Opcode;
use acvm::Language;
use acvm_backend_barretenberg::BackendError;
use clap::Args;
use iter_extended::{try_vecmap, vecmap};
use iter_extended::vecmap;
use nargo::package::Package;
use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection};
use noirc_driver::CompileOptions;
use noirc_driver::{CompileOptions, CompiledContract, CompiledProgram};
use noirc_frontend::graph::CrateName;
use prettytable::{row, table, Row};
use rayon::prelude::*;
use serde::Serialize;

use crate::backends::Backend;
use crate::errors::CliError;

use super::{
compile_cmd::{compile_bin_package, compile_contract_package},
NargoConfig,
};
use super::{compile_cmd::compile_workspace, NargoConfig};

/// Provides detailed information on a circuit
///
Expand Down Expand Up @@ -52,30 +49,30 @@ pub(crate) fn run(
let selection = args.package.map_or(default_selection, PackageSelection::Selected);
let workspace = resolve_workspace_from_toml(&toml_path, selection)?;

let mut info_report = InfoReport::default();

let (np_language, is_opcode_supported) = backend.get_backend_info()?;
for package in &workspace {
if package.is_contract() {
let contract_info = count_opcodes_and_gates_in_contracts(
backend,
package,
&args.compile_options,
np_language,
&is_opcode_supported,
)?;
info_report.contracts.push(contract_info);
} else {
let program_info = count_opcodes_and_gates_in_program(
backend,
package,
&args.compile_options,
np_language,
&is_opcode_supported,
)?;
info_report.programs.push(program_info);
}
}
let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace
.into_iter()
.filter(|package| !package.is_library())
.cloned()
.partition(|package| package.is_binary());

let (compiled_programs, compiled_contracts) =
compile_workspace(backend, &binary_packages, &contract_packages, &args.compile_options)?;

let (np_language, _) = backend.get_backend_info()?;
let program_info = binary_packages
.into_par_iter()
.zip(compiled_programs)
.map(|(package, program)| {
count_opcodes_and_gates_in_program(backend, program, &package, np_language)
})
.collect::<Result<_, _>>()?;

let contract_info = compiled_contracts
.into_par_iter()
.map(|contract| count_opcodes_and_gates_in_contract(backend, contract, np_language))
.collect::<Result<_, _>>()?;

let info_report = InfoReport { programs: program_info, contracts: contract_info };

if args.json {
// Expose machine-readable JSON data.
Expand Down Expand Up @@ -169,15 +166,10 @@ impl From<ContractInfo> for Vec<Row> {

fn count_opcodes_and_gates_in_program(
backend: &Backend,
compiled_program: CompiledProgram,
package: &Package,
compile_options: &CompileOptions,
np_language: Language,
is_opcode_supported: &impl Fn(&Opcode) -> bool,
language: Language,
) -> Result<ProgramInfo, CliError> {
let compiled_program =
compile_bin_package(package, compile_options, np_language, &is_opcode_supported)?;
let (language, _) = backend.get_backend_info()?;

Ok(ProgramInfo {
name: package.name.to_string(),
language,
Expand All @@ -186,24 +178,22 @@ fn count_opcodes_and_gates_in_program(
})
}

fn count_opcodes_and_gates_in_contracts(
fn count_opcodes_and_gates_in_contract(
backend: &Backend,
package: &Package,
compile_options: &CompileOptions,
np_language: Language,
is_opcode_supported: &impl Fn(&Opcode) -> bool,
contract: CompiledContract,
language: Language,
) -> Result<ContractInfo, CliError> {
let contract =
compile_contract_package(package, compile_options, np_language, &is_opcode_supported)?;
let (language, _) = backend.get_backend_info()?;

let functions = try_vecmap(contract.functions, |function| -> Result<_, BackendError> {
Ok(FunctionInfo {
name: function.name,
acir_opcodes: function.bytecode.opcodes.len(),
circuit_size: backend.get_exact_circuit_size(&function.bytecode)?,
let functions = contract
.functions
.into_par_iter()
.map(|function| -> Result<_, BackendError> {
Ok(FunctionInfo {
name: function.name,
acir_opcodes: function.bytecode.opcodes.len(),
circuit_size: backend.get_exact_circuit_size(&function.bytecode)?,
})
})
})?;
.collect::<Result<_, _>>()?;

Ok(ContractInfo { name: contract.name, language, functions })
}

0 comments on commit f173c05

Please sign in to comment.