perf: Cache program lookups to reduce filesystem operations
Co-authored-by: aider (openai/andrew/openrouter/qwen/qwen3-coder) <aider@aider.chat>
This commit is contained in:
@@ -7,6 +7,9 @@ use std::io::{Read, Write};
|
|||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{Child, Command, Stdio};
|
use std::process::{Child, Command, Stdio};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::compression_engine::CompressionEngine;
|
use crate::compression_engine::CompressionEngine;
|
||||||
|
|
||||||
@@ -78,22 +81,52 @@ impl CompressionEngineProgram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache for program lookup results to avoid redundant filesystem operations
|
||||||
|
static PROGRAM_CACHE: Lazy<Mutex<HashMap<String, Option<String>>>> =
|
||||||
|
Lazy::new(|| Mutex::new(HashMap::new()));
|
||||||
|
|
||||||
fn get_program_path(program: &str) -> Result<String> {
|
fn get_program_path(program: &str) -> Result<String> {
|
||||||
|
// Check cache first
|
||||||
|
{
|
||||||
|
let cache = PROGRAM_CACHE.lock().unwrap();
|
||||||
|
if let Some(result) = cache.get(program) {
|
||||||
|
return match result {
|
||||||
|
Some(path) => Ok(path.clone()),
|
||||||
|
None => Err(anyhow!("Unable to find binary {} in PATH", program)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug!("COMPRESSION: Looking for executable: {}", program);
|
debug!("COMPRESSION: Looking for executable: {}", program);
|
||||||
if let Ok(path) = env::var("PATH") {
|
let result = if let Ok(path) = env::var("PATH") {
|
||||||
|
let mut found_path = None;
|
||||||
for p in path.split(':') {
|
for p in path.split(':') {
|
||||||
let p_str = format!("{}/{}", p, program);
|
let p_str = format!("{}/{}", p, program);
|
||||||
let stat = fs::metadata(p_str.clone());
|
if let Ok(stat) = fs::metadata(&p_str) {
|
||||||
if let Ok(stat) = stat {
|
let permissions = stat.permissions();
|
||||||
let md = stat;
|
if stat.is_file() && permissions.mode() & 0o111 != 0 {
|
||||||
let permissions = md.permissions();
|
found_path = Some(p_str);
|
||||||
if md.is_file() && permissions.mode() & 0o111 != 0 {
|
break;
|
||||||
return Ok(p_str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
found_path
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store result in cache
|
||||||
|
let mut cache = PROGRAM_CACHE.lock().unwrap();
|
||||||
|
match &result {
|
||||||
|
Some(path) => {
|
||||||
|
cache.insert(program.to_string(), Some(path.clone()));
|
||||||
|
Ok(path.clone())
|
||||||
}
|
}
|
||||||
|
None => {
|
||||||
|
cache.insert(program.to_string(), None);
|
||||||
Err(anyhow!("Unable to find binary {} in PATH", program))
|
Err(anyhow!("Unable to find binary {} in PATH", program))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompressionEngine for CompressionEngineProgram {
|
impl CompressionEngine for CompressionEngineProgram {
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ use std::io;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::meta_plugin::MetaPlugin;
|
use crate::meta_plugin::MetaPlugin;
|
||||||
|
|
||||||
@@ -132,20 +135,50 @@ impl MetaPlugin for MetaPluginProgram {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache for program lookup results to avoid redundant filesystem operations
|
||||||
|
static PROGRAM_CACHE: Lazy<Mutex<HashMap<String, Option<String>>>> =
|
||||||
|
Lazy::new(|| Mutex::new(HashMap::new()));
|
||||||
|
|
||||||
fn get_program_path(program: &str) -> Result<String> {
|
fn get_program_path(program: &str) -> Result<String> {
|
||||||
|
// Check cache first
|
||||||
|
{
|
||||||
|
let cache = PROGRAM_CACHE.lock().unwrap();
|
||||||
|
if let Some(result) = cache.get(program) {
|
||||||
|
return match result {
|
||||||
|
Some(path) => Ok(path.clone()),
|
||||||
|
None => Err(anyhow!("Unable to find binary {} in PATH", program)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
debug!("META: Looking for executable: {}", program);
|
debug!("META: Looking for executable: {}", program);
|
||||||
if let Ok(path) = env::var("PATH") {
|
let result = if let Ok(path) = env::var("PATH") {
|
||||||
|
let mut found_path = None;
|
||||||
for p in path.split(':') {
|
for p in path.split(':') {
|
||||||
let p_str = format!("{}/{}", p, program);
|
let p_str = format!("{}/{}", p, program);
|
||||||
let stat = fs::metadata(p_str.clone());
|
if let Ok(stat) = fs::metadata(&p_str) {
|
||||||
if let Ok(stat) = stat {
|
let permissions = stat.permissions();
|
||||||
let md = stat;
|
if stat.is_file() && permissions.mode() & 0o111 != 0 {
|
||||||
let permissions = md.permissions();
|
found_path = Some(p_str);
|
||||||
if md.is_file() && permissions.mode() & 0o111 != 0 {
|
break;
|
||||||
return Ok(p_str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
found_path
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store result in cache
|
||||||
|
let mut cache = PROGRAM_CACHE.lock().unwrap();
|
||||||
|
match &result {
|
||||||
|
Some(path) => {
|
||||||
|
cache.insert(program.to_string(), Some(path.clone()));
|
||||||
|
Ok(path.clone())
|
||||||
}
|
}
|
||||||
|
None => {
|
||||||
|
cache.insert(program.to_string(), None);
|
||||||
Err(anyhow!("Unable to find binary {} in PATH", program))
|
Err(anyhow!("Unable to find binary {} in PATH", program))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user