diff --git a/Cargo.lock b/Cargo.lock index 563681123ed..e84901d48ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2216,6 +2216,7 @@ dependencies = [ "pprof", "predicates 2.1.5", "prettytable-rs", + "rayon", "rustc_version", "serde", "serde_json", diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index e015e0caefd..ec15975613b 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -33,6 +33,7 @@ toml.workspace = true serde.workspace = true serde_json.workspace = true prettytable-rs = "0.10" +rayon = "1.7.0" thiserror.workspace = true tower.workspace = true async-lsp = { version = "0.0.5", default-features = false, features = [ diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 7a06b43937a..a1569b2d76d 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -23,6 +23,7 @@ use super::fs::program::{ save_contract_to_file, save_debug_artifact_to_file, save_program_to_file, }; use super::NargoConfig; +use rayon::prelude::*; // TODO(#1388): pull this from backend. const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; @@ -63,38 +64,53 @@ pub(crate) fn run( let circuit_dir = workspace.target_directory_path(); let (np_language, is_opcode_supported) = backend.get_backend_info()?; - for package in &workspace { - // If `contract` package type, we're compiling every function in a 'contract' rather than just 'main'. - if package.is_contract() { - let (file_manager, compilation_result) = compile_contracts( - package, - &args.compile_options, - np_language, - &is_opcode_supported, - ); - let contracts_with_debug_artifacts = report_errors( - compilation_result, - &file_manager, - args.compile_options.deny_warnings, - )?; - - save_contracts( - contracts_with_debug_artifacts, - package, - &circuit_dir, - args.output_debug, - ); - } else { - let (file_manager, compilation_result) = - compile_program(package, &args.compile_options, np_language, &is_opcode_supported); - - let (program, debug_artifact) = report_errors( - compilation_result, - &file_manager, - args.compile_options.deny_warnings, - )?; - save_program(debug_artifact, program, package, &circuit_dir, args.output_debug); - } + + let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace + .members + .iter() + .filter(|package| !package.is_library()) + .partition(|package| package.is_binary()); + + // Compile all of the packages in parallel. + let program_results: Vec<(FileManager, CompilationResult<(CompiledProgram, DebugArtifact)>)> = + binary_packages + .par_iter() + .map(|package| { + compile_program(package, &args.compile_options, np_language, &is_opcode_supported) + }) + .collect(); + let contract_results: Vec<( + FileManager, + CompilationResult>, + )> = contract_packages + .par_iter() + .map(|package| { + compile_contracts(package, &args.compile_options, np_language, &is_opcode_supported) + }) + .collect(); + + // Report any warnings/errors which were encountered during compilation. + let compiled_programs: Vec<(CompiledProgram, DebugArtifact)> = program_results + .into_iter() + .map(|(file_manager, compilation_result)| { + report_errors(compilation_result, &file_manager, args.compile_options.deny_warnings) + }) + .collect::>()?; + let compiled_contracts: Vec> = contract_results + .into_iter() + .map(|(file_manager, compilation_result)| { + report_errors(compilation_result, &file_manager, args.compile_options.deny_warnings) + }) + .collect::>()?; + + // Save build artifacts to disk. + for (package, (program, debug_artifact)) in binary_packages.into_iter().zip(compiled_programs) { + save_program(debug_artifact, program, package, &circuit_dir, args.output_debug); + } + for (package, contracts_with_debug_artifacts) in + contract_packages.into_iter().zip(compiled_contracts) + { + save_contracts(contracts_with_debug_artifacts, package, &circuit_dir, args.output_debug); } Ok(())