Performance improvements

This commit is contained in:
Ajeet D'Souza 2020-04-05 20:44:23 +05:30
parent 4414898a06
commit 342954cda0
8 changed files with 68 additions and 60 deletions

14
Cargo.lock generated
View File

@ -49,7 +49,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -295,15 +295,15 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.105"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde_derive 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
version = "1.0.105"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -432,7 +432,7 @@ dependencies = [
"bstr 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -475,8 +475,8 @@ dependencies = [
"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
"checksum regex-automata 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
"checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
"checksum serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)" = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff"
"checksum serde_derive 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)" = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8"
"checksum serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
"checksum serde_derive 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)" = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum structopt 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d"
"checksum structopt-derive 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430"

View File

@ -17,7 +17,7 @@ anyhow = "1.0.28"
bincode = "1.2.1"
clap = "2.33.0"
dirs = "2.0.2"
serde = { version = "1.0.105", features = ["derive"] }
serde = { version = "1.0.106", features = ["derive"] }
structopt = "0.3.12"
uuid = { version = "0.8.1", features = ["v4"] }

View File

@ -121,7 +121,7 @@ impl DB {
continue;
};
let split_line = line.rsplitn(3, '|').collect::<Vec<&str>>();
let split_line = line.rsplitn(3, '|').collect::<Vec<_>>();
match split_line.as_slice() {
[epoch_str, rank_str, path_str] => {
@ -215,7 +215,7 @@ impl DB {
Ok(())
}
pub fn query(&mut self, keywords: &[String], now: Epoch) -> Option<Dir> {
pub fn query(&mut self, keywords: &[String], now: Epoch) -> Option<&Dir> {
let (idx, dir, _) = self
.data
.dirs
@ -228,7 +228,8 @@ impl DB {
})?;
if dir.is_dir() {
Some(dir.to_owned())
// FIXME: change this to Some(dir) once the MIR borrow checker comes to stable Rust
Some(&self.data.dirs[idx])
} else {
self.data.dirs.swap_remove(idx);
self.modified = true;
@ -236,7 +237,7 @@ impl DB {
}
}
pub fn query_all(&mut self, keywords: &[String]) -> Vec<Dir> {
pub fn query_all<'a>(&'a mut self, keywords: &'a [String]) -> impl Iterator<Item = &'a Dir> {
let orig_len = self.data.dirs.len();
self.data.dirs.retain(Dir::is_dir);
@ -247,15 +248,17 @@ impl DB {
self.data
.dirs
.iter()
.filter(|dir| dir.is_match(&keywords))
.cloned()
.collect()
.filter(move |dir| dir.is_match(keywords))
}
pub fn remove<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
let path_canonicalized;
let path_abs = match path.as_ref().canonicalize() {
Ok(path_abs) => path_abs,
Err(_) => path.as_ref().to_path_buf(),
Ok(path_abs) => {
path_canonicalized = path_abs;
&path_canonicalized
}
Err(_) => path.as_ref(),
};
if let Some(idx) = self.data.dirs.iter().position(|dir| dir.path == path_abs) {

View File

@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
pub use f64 as Rank;
pub use i64 as Epoch; // use a signed integer so subtraction can be performed on it
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct Dir {
pub path: PathBuf,
pub rank: Rank,

View File

@ -15,20 +15,25 @@ pub struct Add {
impl Add {
pub fn run(&self) -> Result<()> {
let mut db = util::get_db()?;
let now = util::get_current_time()?;
let maxage = config::zo_maxage()?;
let excluded_dirs = config::zo_exclude_dirs();
let current_dir;
let path = match &self.path {
Some(path) => path.clone(),
None => env::current_dir().context("unable to fetch current directory")?,
Some(path) => path,
None => {
current_dir = env::current_dir().context("unable to fetch current directory")?;
&current_dir
}
};
if excluded_dirs.contains(&path) {
let excluded_dirs = config::zo_exclude_dirs();
if excluded_dirs.contains(path) {
return Ok(());
}
let mut db = util::get_db()?;
let maxage = config::zo_maxage()?;
let now = util::get_current_time()?;
db.add(path, maxage, now)
}
}

View File

@ -45,8 +45,6 @@ impl Init {
let stdout = io::stdout();
let mut handle = stdout.lock();
// If any `writeln!` call fails to write to stdout, we assume the user's
// computer is on fire and panic.
let z = config.z;
writeln!(handle, "{}", z(&self.z_cmd)).unwrap();

View File

@ -15,7 +15,7 @@ pub struct Query {
}
impl Query {
pub fn run(mut self) -> Result<()> {
pub fn run(&self) -> Result<()> {
let path_opt = if self.interactive {
self.query_interactive()?
} else {
@ -35,7 +35,7 @@ impl Query {
Ok(())
}
fn query(&mut self) -> Result<Option<Vec<u8>>> {
fn query(&self) -> Result<Option<Vec<u8>>> {
if let [path] = self.keywords.as_slice() {
if Path::new(path).is_dir() {
return Ok(Some(path.as_bytes().to_vec()));
@ -44,11 +44,13 @@ impl Query {
let now = util::get_current_time()?;
for keyword in &mut self.keywords {
*keyword = keyword.to_lowercase();
}
let keywords = self
.keywords
.iter()
.map(|keyword| keyword.to_lowercase())
.collect::<Vec<_>>();
let path_opt = util::get_db()?.query(&self.keywords, now).map(|dir| {
let path_opt = util::get_db()?.query(&keywords, now).map(|dir| {
// `path_to_bytes` is guaranteed to succeed here since
// the path has already been queried successfully
let path_bytes = util::path_to_bytes(&dir.path).unwrap();
@ -58,14 +60,17 @@ impl Query {
Ok(path_opt)
}
fn query_interactive(&mut self) -> Result<Option<Vec<u8>>> {
fn query_interactive(&self) -> Result<Option<Vec<u8>>> {
let now = util::get_current_time()?;
for keyword in &mut self.keywords {
*keyword = keyword.to_lowercase();
}
let keywords = self
.keywords
.iter()
.map(|keyword| keyword.to_lowercase())
.collect::<Vec<_>>();
let dirs = util::get_db()?.query_all(&self.keywords);
let mut db = util::get_db()?;
let dirs = db.query_all(&keywords);
util::fzf_helper(now, dirs)
}
}

View File

@ -4,7 +4,7 @@ use crate::dir::{Dir, Epoch};
use anyhow::{anyhow, bail, Context, Result};
use std::cmp::{Ordering, PartialOrd};
use std::cmp::Reverse;
use std::io::{Read, Write};
use std::path::Path;
use std::process::{Command, Stdio};
@ -49,9 +49,12 @@ pub fn get_current_time() -> Result<Epoch> {
Ok(current_time as Epoch)
}
pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<Vec<u8>>> {
pub fn fzf_helper<'a, I>(now: Epoch, dirs: I) -> Result<Option<Vec<u8>>>
where
I: IntoIterator<Item = &'a Dir>,
{
let mut fzf = Command::new("fzf")
.arg("-n2..")
.args(&["-n2..", "--no-sort"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
@ -62,26 +65,20 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<Vec<u8>>> {
.as_mut()
.ok_or_else(|| anyhow!("could not connect to fzf stdin"))?;
for dir in dirs.iter_mut() {
dir.rank = dir.get_frecency(now);
}
let mut dir_frecencies = dirs
.into_iter()
.map(|dir| (dir, clamp(dir.get_frecency(now), 0.0, 9999.0) as i32))
.collect::<Vec<_>>();
dirs.sort_unstable_by(|dir1, dir2| {
dir1.rank
.partial_cmp(&dir2.rank)
.unwrap_or(Ordering::Equal)
.reverse()
});
dir_frecencies.sort_unstable_by_key(|&(dir, frecency)| Reverse((frecency, &dir.path)));
for dir in dirs.iter() {
for &(dir, frecency) in dir_frecencies.iter() {
// ensure that frecency fits in 4 characters
let frecency = clamp(dir.rank, 0.0, 9999.0);
if let Some(path_bytes) = path_to_bytes(&dir.path) {
(|| {
write!(fzf_stdin, "{:>4.0} ", frecency)?;
write!(fzf_stdin, "{:>4} ", frecency)?;
fzf_stdin.write_all(path_bytes)?;
fzf_stdin.write_all(b"\n")
writeln!(fzf_stdin)
})()
.context("could not write into fzf stdin")?;
}
@ -125,11 +122,11 @@ pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<Vec<u8>>> {
pub fn clamp(val: f64, min: f64, max: f64) -> f64 {
assert!(min <= max);
if val < min {
min
} else if val > max {
if val > max {
max
} else {
} else if val > min {
val
} else {
min
}
}