Skip to content

Commit

Permalink
Improve CI build times (#1675)
Browse files Browse the repository at this point in the history
This change makes two updates that have major benefit for overall build
times:

- Convert Rust integration tests into unit tests, as this keeps
compilation to one executable instead of many.
- Use cmdline overrides in build.py when running unit tests to avoid
LTO.

Between these two changes, the build portion of `cargo test` on Windows
drops from ~17 min to ~3 min, and overall build times across all
platforms is improved. Note that this does NOT change the optimization
levels for builds for other components like WASM and Python, so scenario
test and production optimization and binary performance should be
unaffected.
  • Loading branch information
swernli authored Jun 27, 2024
1 parent c941c67 commit 5376781
Show file tree
Hide file tree
Showing 77 changed files with 131 additions and 140 deletions.
18 changes: 11 additions & 7 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,18 +214,22 @@ def use_python_env(folder):
step_end()

if build_cli:
step_start("Building the command line compiler")
cargo_build_args = ["cargo", "build"]
if build_type == "release":
cargo_build_args.append("--release")
subprocess.run(cargo_build_args, check=True, text=True, cwd=root_dir)

if run_tests:
print("Running tests for the command line compiler")
step_start("Running Rust unit tests")
cargo_test_args = ["cargo", "test"]
if build_type == "release":
cargo_test_args.append("--release")
# Disable LTO for release tests to speed up compilation
cargo_test_args.append("--config")
cargo_test_args.append('profile.release.lto="off"')
subprocess.run(cargo_test_args, check=True, text=True, cwd=root_dir)
step_end()

step_start("Building the command line compiler")
cargo_build_args = ["cargo", "build", "--bin", "qsc"]
if build_type == "release":
cargo_build_args.append("--release")
subprocess.run(cargo_build_args, check=True, text=True, cwd=root_dir)
step_end()


Expand Down
3 changes: 3 additions & 0 deletions compiler/qsc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,17 @@ doctest = false
[[bin]]
name = "qsc"
bench = false
test = false

[[bin]]
name = "qsi"
bench = false
test = false

[[bin]]
name = "memtest"
bench = false
test = false

[[bench]]
name = "large"
Expand Down
6 changes: 6 additions & 0 deletions compiler/qsc_formatter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ indoc = { workspace = true }

[lib]
doctest = false

[[bin]]
name = "qsc_formatter"
bench = false
test = false

Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use clap::{crate_version, Parser};
use qsc_formatter::formatter::{calculate_format_edits, format_str};
use std::{
env,
fmt::Display,
path::{Path, PathBuf},
};
mod formatter;
use clap::{crate_version, Parser};
use formatter::{calculate_format_edits, format_str};

#[derive(Debug, Parser)]
#[command(name = "fmt", version = crate_version!())]
Expand Down
3 changes: 3 additions & 0 deletions compiler/qsc_partial_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
//! It does this by evaluating all purely classical expressions and generating RIR instructions for expressions that are
//! not purely classical.

#[cfg(test)]
mod tests;

mod evaluation_context;
mod management;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

mod arrays;
mod assigns;
mod bindings;
mod branching;
mod calls;
mod classical_args;
mod dynamic_vars;
mod intrinsics;
mod loops;
mod misc;
mod operators;
mod output_recording;
mod qubits;
mod results;
mod returns;

use crate::{partially_evaluate, Error, ProgramEntry};
use expect_test::Expect;
use qsc::{incremental::Compiler, PackageType};
use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
use qsc_fir::fir::PackageStore;
use qsc_frontend::compile::{PackageStore as HirPackageStore, SourceMap};
use qsc_lowerer::{map_hir_package_to_fir, Lowerer};
use qsc_partial_eval::{partially_evaluate, Error, ProgramEntry};
use qsc_rca::{Analyzer, PackageStoreComputeProperties};
use qsc_rir::{
passes::check_and_transform,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@
clippy::too_many_lines
)]

pub mod test_utils;

use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{
use super::{
assert_block_instructions, assert_callable, assert_error, get_partial_evaluation_error,
get_rir_program,
};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};

#[test]
fn array_with_dynamic_content() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@
clippy::too_many_lines
)]

pub mod test_utils;

use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{
use super::{
assert_block_instructions, assert_blocks, assert_callable, assert_error,
get_partial_evaluation_error, get_rir_program,
};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};

#[test]
fn assigning_result_literal_updates_value() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
clippy::too_many_lines
)]

pub mod test_utils;

use super::{assert_block_instructions, assert_blocks, assert_callable, get_rir_program};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{assert_block_instructions, assert_blocks, assert_callable, get_rir_program};

#[test]
fn immutable_result_binding_does_not_generate_store_instruction() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
clippy::too_many_lines
)]

pub mod test_utils;

use super::{
assert_blocks, assert_callable, assert_error, get_partial_evaluation_error, get_rir_program,
};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::CallableId;
use test_utils::{
assert_blocks, assert_callable, assert_error, get_partial_evaluation_error, get_rir_program,
};

#[test]
fn if_expression_with_true_condition() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@
clippy::too_many_lines
)]

pub mod test_utils;

use expect_test::expect;
use indoc::indoc;
use qsc::TargetCapabilityFlags;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{
use super::{
assert_block_instructions, assert_blocks, assert_callable, assert_error,
get_partial_evaluation_error_with_capabilities, get_rir_program,
get_rir_program_with_capabilities,
};
use expect_test::expect;
use indoc::indoc;
use qsc::TargetCapabilityFlags;
use qsc_rir::rir::{BlockId, CallableId};

#[test]
fn call_to_single_qubit_unitary_with_two_calls_to_the_same_intrinsic() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

#![allow(clippy::needless_raw_string_hashes)]

pub mod test_utils;

use super::{assert_block_instructions, assert_callable, get_rir_program};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{assert_block_instructions, assert_callable, get_rir_program};

#[test]
fn call_to_intrinsic_operation_using_double_literal() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@

#![allow(clippy::needless_raw_string_hashes, clippy::similar_names)]

pub mod test_utils;

use super::{assert_blocks, assert_callable, get_rir_program};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::CallableId;
use test_utils::{assert_callable, get_rir_program};

use crate::test_utils::assert_blocks;

#[test]
fn dynamic_int_from_if_expression_with_single_measurement_comparison_and_classical_blocks() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

#![allow(clippy::needless_raw_string_hashes)]

pub mod test_utils;

use super::{assert_block_instructions, assert_blocks, assert_callable, get_rir_program};
use expect_test::{expect, Expect};
use indoc::{formatdoc, indoc};
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{assert_block_instructions, assert_blocks, assert_callable, get_rir_program};

fn check_call_to_single_qubit_instrinsic_adds_callable_and_generates_instruction(
intrinsic_name: &str,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

#![allow(clippy::needless_raw_string_hashes)]

pub mod test_utils;

use super::{assert_block_instructions, assert_callable, get_rir_program};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{assert_block_instructions, assert_callable, get_rir_program};

#[test]
fn unitary_call_within_a_for_loop() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@

#![allow(clippy::needless_raw_string_hashes, clippy::similar_names)]

pub mod test_utils;

use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{
use super::{
assert_block_instructions, assert_blocks, assert_callable, assert_error,
get_partial_evaluation_error, get_rir_program,
};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};

#[test]
fn unitary_call_within_an_if_with_classical_condition_within_a_for_loop() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@

#![allow(clippy::needless_raw_string_hashes)]

pub mod test_utils;

use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{
use super::{
assert_block_instructions, assert_blocks, assert_callable, assert_error,
get_partial_evaluation_error, get_rir_program,
};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};

#[test]
fn leading_positive_unary_operator_does_not_generate_rir_instruction() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@

#![allow(clippy::needless_raw_string_hashes)]

use super::{assert_error, get_partial_evaluation_error, get_rir_program};
use expect_test::expect;
use indoc::indoc;
use test_utils::{assert_error, get_partial_evaluation_error, get_rir_program};

pub mod test_utils;

#[test]
fn output_recording_for_tuple_of_different_types() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

#![allow(clippy::needless_raw_string_hashes)]

pub mod test_utils;

use super::{assert_block_instructions, assert_callable, get_rir_program};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{assert_block_instructions, assert_callable, get_rir_program};

#[test]
fn qubit_ids_are_correct_for_allocate_use_release_one_qubit() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

#![allow(clippy::needless_raw_string_hashes)]

pub mod test_utils;

use super::{assert_block_instructions, assert_callable, get_rir_program};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{assert_block_instructions, assert_callable, get_rir_program};

#[test]
fn result_ids_are_correct_for_measuring_and_resetting_one_qubit() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@
clippy::too_many_lines
)]

pub mod test_utils;

use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};
use test_utils::{
use super::{
assert_block_instructions, assert_blocks, assert_callable, assert_error,
get_partial_evaluation_error, get_rir_program,
};
use expect_test::expect;
use indoc::indoc;
use qsc_rir::rir::{BlockId, CallableId};

#[test]
fn non_classical_entry_point_with_classical_implicit_return() {
Expand Down
3 changes: 3 additions & 0 deletions compiler/qsc_project/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
//! This includes locating a manifest file in the filesystem, loading and parsing
//! the manifest, and determining which files are members of the project.

#[cfg(test)]
mod tests;

mod error;
#[cfg(feature = "fs")]
mod fs;
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ use expect_test::Expect;
use qsc_project::{FileSystem, Manifest, StdFs};

pub fn check(project_path: &PathBuf, expect: &Expect) {
// use the path to the src folder as the root path
let mut root_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
root_path.push(PathBuf::from("tests/projects"));
root_path.push("src");
root_path.push("tests");
root_path.push("projects");
let mut absolute_project_path = root_path.clone();
absolute_project_path.push(project_path);
let manifest = Manifest::load_from_path(absolute_project_path)
Expand Down
Loading

0 comments on commit 5376781

Please sign in to comment.