From 558d415e12cb2798dd588e435abb8b03a4b3cd4f Mon Sep 17 00:00:00 2001 From: vikingowl Date: Sat, 28 Mar 2026 08:40:22 +0100 Subject: [PATCH] perf(config): replace which subprocesses with in-process PATH scan detect_terminal() was spawning up to 17 'which' subprocesses sequentially on every startup. Replace with std::env::split_paths + is_file() check. Eliminates 200-500ms of fork+exec overhead on cold cache. --- crates/owlry-core/src/config/mod.rs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/crates/owlry-core/src/config/mod.rs b/crates/owlry-core/src/config/mod.rs index 065e67e..f611e41 100644 --- a/crates/owlry-core/src/config/mod.rs +++ b/crates/owlry-core/src/config/mod.rs @@ -2,7 +2,6 @@ use log::{debug, info, warn}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; -use std::process::Command; use crate::paths; @@ -522,12 +521,15 @@ fn detect_de_terminal() -> Option { None } -/// Check if a command exists in PATH +/// Check if a command exists in PATH (in-process, no subprocess spawning) fn command_exists(cmd: &str) -> bool { - Command::new("which") - .arg(cmd) - .output() - .map(|o| o.status.success()) + std::env::var_os("PATH") + .map(|paths| { + std::env::split_paths(&paths).any(|dir| { + let full = dir.join(cmd); + full.is_file() + }) + }) .unwrap_or(false) } @@ -591,3 +593,17 @@ impl Config { Ok(()) } } + +#[cfg(test)] +mod tests { + #[test] + fn command_exists_finds_sh() { + // /bin/sh exists on every Unix system + assert!(super::command_exists("sh")); + } + + #[test] + fn command_exists_rejects_nonexistent() { + assert!(!super::command_exists("owlry_nonexistent_binary_abc123")); + } +}