mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 13:36:07 +02:00
add some startup performance metrics (#7851)
# Description This PR changes the old performance logging with `Instant` timers. I'm not sure if this is the best way to do it but it does help reveal where time is being spent on startup. This is what it looks like when you launch nushell with `cargo run -- --log-level info`. I'm using the `info` log level exclusively for performance monitoring at this point.  ## After Startup Since you're in the repl, you can continue running commands. Here's the output of `ls`, for instance.  Note that the above screenshots are in debug mode, so they're much slower than release. # User-Facing Changes # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
This commit is contained in:
@ -110,8 +110,6 @@ pub(crate) fn read_config_file(
|
||||
|
||||
eval_config_contents(config_path, engine_state, stack);
|
||||
}
|
||||
|
||||
info!("read_config_file {}:{}:{}", file!(), line!(), column!());
|
||||
}
|
||||
|
||||
pub(crate) fn read_loginshell_file(engine_state: &mut EngineState, stack: &mut Stack) {
|
||||
@ -200,8 +198,6 @@ pub(crate) fn setup_config(
|
||||
#[cfg(feature = "plugin")]
|
||||
read_plugin_file(engine_state, stack, plugin_file, NUSHELL_FOLDER);
|
||||
|
||||
info!("read_config_file {}:{}:{}", file!(), line!(), column!());
|
||||
|
||||
read_config_file(engine_state, stack, env_file, true);
|
||||
read_config_file(engine_state, stack, config_file, false);
|
||||
|
||||
|
117
src/main.rs
117
src/main.rs
@ -15,7 +15,7 @@ use crate::{
|
||||
logger::{configure, logger},
|
||||
terminal::acquire_terminal,
|
||||
};
|
||||
use log::{info, Level};
|
||||
use log::Level;
|
||||
use miette::Result;
|
||||
#[cfg(feature = "plugin")]
|
||||
use nu_cli::read_plugin_file;
|
||||
@ -26,16 +26,17 @@ use nu_cli::{
|
||||
use nu_command::create_default_context;
|
||||
use nu_parser::{escape_for_script_arg, escape_quote_string};
|
||||
use nu_protocol::{util::BufferedReader, PipelineData, RawStream};
|
||||
use nu_utils::utils::perf;
|
||||
use signals::{ctrlc_protection, sigquit_protection};
|
||||
use std::{
|
||||
io::BufReader,
|
||||
str::FromStr,
|
||||
sync::{atomic::AtomicBool, Arc},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let start_time = Instant::now();
|
||||
let entire_start_time = std::time::Instant::now();
|
||||
let mut start_time = std::time::Instant::now();
|
||||
let miette_hook = std::panic::take_hook();
|
||||
std::panic::set_hook(Box::new(move |x| {
|
||||
crossterm::terminal::disable_raw_mode().expect("unable to disable raw mode");
|
||||
@ -113,37 +114,6 @@ fn main() -> Result<()> {
|
||||
let parsed_nu_cli_args = parse_commandline_args(&nushell_commandline_args, &mut engine_state)
|
||||
.unwrap_or_else(|_| std::process::exit(1));
|
||||
|
||||
set_config_path(
|
||||
&mut engine_state,
|
||||
&init_cwd,
|
||||
"config.nu",
|
||||
"config-path",
|
||||
&parsed_nu_cli_args.config_file,
|
||||
);
|
||||
|
||||
set_config_path(
|
||||
&mut engine_state,
|
||||
&init_cwd,
|
||||
"env.nu",
|
||||
"env-path",
|
||||
&parsed_nu_cli_args.env_file,
|
||||
);
|
||||
|
||||
// keep this condition in sync with the branches below
|
||||
acquire_terminal(
|
||||
parsed_nu_cli_args.commands.is_none()
|
||||
&& (script_name.is_empty() || parsed_nu_cli_args.interactive_shell.is_some()),
|
||||
);
|
||||
|
||||
if let Some(t) = parsed_nu_cli_args.threads {
|
||||
// 0 means to let rayon decide how many threads to use
|
||||
let threads = t.as_i64().unwrap_or(0);
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(threads as usize)
|
||||
.build_global()
|
||||
.expect("error setting number of threads");
|
||||
}
|
||||
|
||||
if let Some(level) = parsed_nu_cli_args.log_level.map(|level| level.item) {
|
||||
let level = if Level::from_str(&level).is_ok() {
|
||||
level
|
||||
@ -159,9 +129,48 @@ fn main() -> Result<()> {
|
||||
.unwrap_or_else(|| "stderr".to_string());
|
||||
|
||||
logger(|builder| configure(&level, &target, builder))?;
|
||||
info!("start logging {}:{}:{}", file!(), line!(), column!());
|
||||
// info!("start logging {}:{}:{}", file!(), line!(), column!());
|
||||
perf("start logging", start_time, file!(), line!(), column!());
|
||||
}
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
set_config_path(
|
||||
&mut engine_state,
|
||||
&init_cwd,
|
||||
"config.nu",
|
||||
"config-path",
|
||||
&parsed_nu_cli_args.config_file,
|
||||
);
|
||||
|
||||
set_config_path(
|
||||
&mut engine_state,
|
||||
&init_cwd,
|
||||
"env.nu",
|
||||
"env-path",
|
||||
&parsed_nu_cli_args.env_file,
|
||||
);
|
||||
perf("set_config_path", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
// keep this condition in sync with the branches below
|
||||
acquire_terminal(
|
||||
parsed_nu_cli_args.commands.is_none()
|
||||
&& (script_name.is_empty() || parsed_nu_cli_args.interactive_shell.is_some()),
|
||||
);
|
||||
perf("acquire_terminal", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
if let Some(t) = parsed_nu_cli_args.threads {
|
||||
// 0 means to let rayon decide how many threads to use
|
||||
let threads = t.as_i64().unwrap_or(0);
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(threads as usize)
|
||||
.build_global()
|
||||
.expect("error setting number of threads");
|
||||
}
|
||||
perf("set rayon threads", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
if let Some(testbin) = &parsed_nu_cli_args.testbin {
|
||||
// Call out to the correct testbin
|
||||
match testbin.item.as_str() {
|
||||
@ -181,6 +190,9 @@ fn main() -> Result<()> {
|
||||
}
|
||||
std::process::exit(0)
|
||||
}
|
||||
perf("run test_bins", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
let input = if let Some(redirect_stdin) = &parsed_nu_cli_args.redirect_stdin {
|
||||
let stdin = std::io::stdin();
|
||||
let buf_reader = BufReader::new(stdin);
|
||||
@ -201,15 +213,17 @@ fn main() -> Result<()> {
|
||||
} else {
|
||||
PipelineData::empty()
|
||||
};
|
||||
perf("redirect stdin", start_time, file!(), line!(), column!());
|
||||
|
||||
info!("redirect_stdin {}:{}:{}", file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
// First, set up env vars as strings only
|
||||
gather_parent_env_vars(&mut engine_state, &init_cwd);
|
||||
perf("gather env vars", start_time, file!(), line!(), column!());
|
||||
|
||||
let mut stack = nu_protocol::engine::Stack::new();
|
||||
|
||||
if let Some(commands) = &parsed_nu_cli_args.commands {
|
||||
start_time = std::time::Instant::now();
|
||||
#[cfg(feature = "plugin")]
|
||||
read_plugin_file(
|
||||
&mut engine_state,
|
||||
@ -217,7 +231,9 @@ fn main() -> Result<()> {
|
||||
parsed_nu_cli_args.plugin_file,
|
||||
NUSHELL_FOLDER,
|
||||
);
|
||||
perf("read plugins", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
// only want to load config and env if relative argument is provided.
|
||||
if parsed_nu_cli_args.env_file.is_some() {
|
||||
config_files::read_config_file(
|
||||
@ -229,7 +245,9 @@ fn main() -> Result<()> {
|
||||
} else {
|
||||
config_files::read_default_env_file(&mut engine_state, &mut stack)
|
||||
}
|
||||
perf("read env.nu", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
if parsed_nu_cli_args.config_file.is_some() {
|
||||
config_files::read_config_file(
|
||||
&mut engine_state,
|
||||
@ -238,7 +256,9 @@ fn main() -> Result<()> {
|
||||
false,
|
||||
);
|
||||
}
|
||||
perf("read config.nu", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
let ret_val = evaluate_commands(
|
||||
commands,
|
||||
&mut engine_state,
|
||||
@ -246,13 +266,16 @@ fn main() -> Result<()> {
|
||||
input,
|
||||
parsed_nu_cli_args.table_mode,
|
||||
);
|
||||
info!("-c command execution {}:{}:{}", file!(), line!(), column!());
|
||||
perf("evaluate_commands", start_time, file!(), line!(), column!());
|
||||
|
||||
match ret_val {
|
||||
Ok(Some(exit_code)) => std::process::exit(exit_code as i32),
|
||||
Ok(None) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
} else if !script_name.is_empty() && parsed_nu_cli_args.interactive_shell.is_none() {
|
||||
start_time = std::time::Instant::now();
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
read_plugin_file(
|
||||
&mut engine_state,
|
||||
@ -260,7 +283,9 @@ fn main() -> Result<()> {
|
||||
parsed_nu_cli_args.plugin_file,
|
||||
NUSHELL_FOLDER,
|
||||
);
|
||||
perf("read plugins", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
// only want to load config and env if relative argument is provided.
|
||||
if parsed_nu_cli_args.env_file.is_some() {
|
||||
config_files::read_config_file(
|
||||
@ -272,7 +297,9 @@ fn main() -> Result<()> {
|
||||
} else {
|
||||
config_files::read_default_env_file(&mut engine_state, &mut stack)
|
||||
}
|
||||
perf("read env.nu", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
if parsed_nu_cli_args.config_file.is_some() {
|
||||
config_files::read_config_file(
|
||||
&mut engine_state,
|
||||
@ -281,7 +308,9 @@ fn main() -> Result<()> {
|
||||
false,
|
||||
);
|
||||
}
|
||||
perf("read config.nu", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
let ret_val = evaluate_file(
|
||||
script_name,
|
||||
&args_to_script,
|
||||
@ -289,7 +318,9 @@ fn main() -> Result<()> {
|
||||
&mut stack,
|
||||
input,
|
||||
);
|
||||
perf("evaluate_file", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
let last_exit_code = stack.get_env_var(&engine_state, "LAST_EXIT_CODE");
|
||||
if let Some(last_exit_code) = last_exit_code {
|
||||
let value = last_exit_code.as_integer();
|
||||
@ -299,10 +330,12 @@ fn main() -> Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
info!("eval_file execution {}:{}:{}", file!(), line!(), column!());
|
||||
perf("get exit code", start_time, file!(), line!(), column!());
|
||||
|
||||
ret_val
|
||||
} else {
|
||||
start_time = std::time::Instant::now();
|
||||
|
||||
setup_config(
|
||||
&mut engine_state,
|
||||
&mut stack,
|
||||
@ -312,15 +345,17 @@ fn main() -> Result<()> {
|
||||
parsed_nu_cli_args.env_file,
|
||||
parsed_nu_cli_args.login_shell.is_some(),
|
||||
);
|
||||
perf("setup_config", start_time, file!(), line!(), column!());
|
||||
|
||||
start_time = std::time::Instant::now();
|
||||
let ret_val = evaluate_repl(
|
||||
&mut engine_state,
|
||||
&mut stack,
|
||||
config_files::NUSHELL_FOLDER,
|
||||
parsed_nu_cli_args.execute,
|
||||
start_time,
|
||||
entire_start_time,
|
||||
);
|
||||
info!("repl eval {}:{}:{}", file!(), line!(), column!());
|
||||
perf("evaluate_repl", start_time, file!(), line!(), column!());
|
||||
|
||||
ret_val
|
||||
}
|
||||
|
Reference in New Issue
Block a user