Optimize compilation time (#320)

* Print `rerun-if-changed=build.rs` in `build.rs`
* Optimize compile-time: Extract `bin/src/lib.rs`
   
   so that `cargo-binstall (lib)` can be compiled in parallel to other
   deps.
* Refactor: Extract new mod `bin/src/bin_utils.rs`
* Extract new fn `MainExit::new`
* Refactor: Extract new fn `run_tokio_main`
* Handle `Runtime::new` err gracefully in `run_tokio_main`
   instead of `panic!`ing, return the error as `BinstallError`
* Avoid mixing `eprintln` and `error` in `MainExit::report`
* Set profile for `build-override`
   to speedup building of `build.rs` and proc macros.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2022-08-27 21:27:39 +10:00 committed by GitHub
parent e39a02aa92
commit 305cda3336
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 95 additions and 53 deletions

View file

@ -14,3 +14,19 @@ lto = true
codegen-units = 1 codegen-units = 1
panic = "abort" panic = "abort"
strip = "symbols" strip = "symbols"
[profile.dev.build-override]
opt-level = 0
codegen-units = 1024
debug = false
debug-assertions = false
overflow-checks = false
incremental = false
[profile.release.build-override]
opt-level = 0
codegen-units = 1024
debug = false
debug-assertions = false
overflow-checks = false
incremental = false

View file

@ -1,3 +1,5 @@
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
embed_resource::compile("manifest.rc"); embed_resource::compile("manifest.rc");
} }

View file

@ -0,0 +1,60 @@
use std::{
future::Future,
process::{ExitCode, Termination},
time::Duration,
};
use binstall::errors::BinstallError;
use binstall::helpers::{signal::cancel_on_user_sig_term, tasks::AutoAbortJoinHandle};
use log::{error, info};
use miette::Result;
use tokio::runtime::Runtime;
pub enum MainExit {
Success(Duration),
Error(BinstallError),
Report(miette::Report),
}
impl Termination for MainExit {
fn report(self) -> ExitCode {
match self {
Self::Success(spent) => {
info!("Done in {spent:?}");
ExitCode::SUCCESS
}
Self::Error(err) => err.report(),
Self::Report(err) => {
error!("Fatal error:\n{err:?}");
ExitCode::from(16)
}
}
}
}
impl MainExit {
pub fn new(result: Result<Result<()>, BinstallError>, done: Duration) -> Self {
result.map_or_else(MainExit::Error, |res| {
res.map(|()| MainExit::Success(done)).unwrap_or_else(|err| {
err.downcast::<BinstallError>()
.map(MainExit::Error)
.unwrap_or_else(MainExit::Report)
})
})
}
}
/// This function would start a tokio multithreading runtime,
/// spawn a new task on it that runs `f`, then `block_on` it.
///
/// It will cancel the future if user requested cancellation
/// via signal.
pub fn run_tokio_main<F, T>(f: F) -> Result<T, BinstallError>
where
F: Future<Output = T> + Send + 'static,
T: Send + 'static,
{
let rt = Runtime::new()?;
let handle = AutoAbortJoinHandle::new(rt.spawn(f));
rt.block_on(cancel_on_user_sig_term(handle))
}

5
crates/bin/src/lib.rs Normal file
View file

@ -0,0 +1,5 @@
pub mod args;
pub mod bin_util;
pub mod entry;
pub mod install_path;
pub mod ui;

View file

@ -1,22 +1,13 @@
use std::{ use std::time::Instant;
process::{ExitCode, Termination},
time::{Duration, Instant},
};
use binstall::{ use binstall::helpers::jobserver_client::LazyJobserverClient;
errors::BinstallError, use log::debug;
helpers::{
jobserver_client::LazyJobserverClient, signal::cancel_on_user_sig_term,
tasks::AutoAbortJoinHandle,
},
};
use log::{debug, error, info};
use tokio::runtime::Runtime;
mod args; use cargo_binstall::{
mod entry; args,
mod install_path; bin_util::{run_tokio_main, MainExit},
mod ui; entry, ui,
};
#[cfg(feature = "mimalloc")] #[cfg(feature = "mimalloc")]
#[global_allocator] #[global_allocator]
@ -35,44 +26,10 @@ fn main() -> MainExit {
let start = Instant::now(); let start = Instant::now();
let result = { let result = run_tokio_main(entry::install_crates(args, jobserver_client));
let rt = Runtime::new().unwrap();
let handle =
AutoAbortJoinHandle::new(rt.spawn(entry::install_crates(args, jobserver_client)));
rt.block_on(cancel_on_user_sig_term(handle))
};
let done = start.elapsed(); let done = start.elapsed();
debug!("run time: {done:?}"); debug!("run time: {done:?}");
result.map_or_else(MainExit::Error, |res| { MainExit::new(result, done)
res.map(|()| MainExit::Success(done)).unwrap_or_else(|err| {
err.downcast::<BinstallError>()
.map(MainExit::Error)
.unwrap_or_else(MainExit::Report)
})
})
}
enum MainExit {
Success(Duration),
Error(BinstallError),
Report(miette::Report),
}
impl Termination for MainExit {
fn report(self) -> ExitCode {
match self {
Self::Success(spent) => {
info!("Done in {spent:?}");
ExitCode::SUCCESS
}
Self::Error(err) => err.report(),
Self::Report(err) => {
error!("Fatal error:");
eprintln!("{err:?}");
ExitCode::from(16)
}
}
}
} }

View file

@ -1,4 +1,6 @@
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
// Fetch build target and define this for the compiler // Fetch build target and define this for the compiler
println!( println!(
"cargo:rustc-env=TARGET={}", "cargo:rustc-env=TARGET={}",