perf: eliminate all memory reallocations during sorting (#1846)

This commit is contained in:
三咲雅 · Misaki Masa 2024-10-28 15:36:27 +08:00 committed by GitHub
parent ef1a31a274
commit 4dd24f779c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 64 additions and 53 deletions

82
Cargo.lock generated
View file

@ -74,9 +74,9 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.6.15"
version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
dependencies = [
"anstyle",
"anstyle-parse",
@ -89,36 +89,36 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.8"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
[[package]]
name = "anstyle-parse"
version = "0.2.5"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.1"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.4"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@ -462,9 +462,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "colorchoice"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "compact_str"
@ -561,7 +561,7 @@ dependencies = [
"filedescriptor",
"futures-core",
"libc",
"mio 1.0.2",
"mio",
"parking_lot",
"rustix",
"signal-hook",
@ -773,9 +773,9 @@ dependencies = [
[[package]]
name = "fdeflate"
version = "0.3.5"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab"
checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb"
dependencies = [
"simd-adler32",
]
@ -1410,18 +1410,6 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "mio"
version = "1.0.2"
@ -1455,9 +1443,9 @@ dependencies = [
[[package]]
name = "mlua-sys"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebe026d6bd1583a9cf9080e189030ddaea7e6f5f0deb366a8e26f8a26c4135b8"
checksum = "e9eebac25c35a13285456c88ee2fde93d9aee8bcfdaf03f9d6d12be3391351ec"
dependencies = [
"cc",
"cfg-if",
@ -1504,10 +1492,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]]
name = "notify-fork"
version = "6.1.1"
name = "notify"
version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f610737468f7a95610d2b320b5d5e246b3cd1c3603782680c0f454ac5825b64b"
checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009"
dependencies = [
"bitflags 2.6.0",
"filetime",
@ -1516,17 +1504,17 @@ dependencies = [
"kqueue",
"libc",
"log",
"mio 0.8.11",
"notify-types-fork",
"mio",
"notify-types",
"walkdir",
"windows-sys 0.52.0",
]
[[package]]
name = "notify-types-fork"
name = "notify-types"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc01866a421a4ce1eddc764da8a95b30b82aa0d9d7f33508265c196d4863b18"
checksum = "7393c226621f817964ffb3dc5704f9509e107a8b024b489cc2c1b217378785df"
dependencies = [
"instant",
]
@ -1741,9 +1729,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
[[package]]
name = "pin-utils"
@ -2072,9 +2060,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
[[package]]
name = "rustix"
version = "0.38.37"
version = "0.38.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
dependencies = [
"bitflags 2.6.0",
"errno",
@ -2199,7 +2187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
dependencies = [
"libc",
"mio 1.0.2",
"mio",
"signal-hook",
]
@ -2481,7 +2469,7 @@ dependencies = [
"backtrace",
"bytes",
"libc",
"mio 1.0.2",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
@ -2631,9 +2619,9 @@ dependencies = [
[[package]]
name = "trash"
version = "5.1.1"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33caf2a9be1812a263a4bfce74d2de225fcde12ee7b77001361abd2b34ffdcc4"
checksum = "defe1fdd4232e407b312377885a2c5396764972bddad87baf304753374a1bfc8"
dependencies = [
"chrono",
"libc",
@ -3280,7 +3268,7 @@ dependencies = [
"dirs",
"futures",
"libc",
"notify-fork",
"notify",
"parking_lot",
"ratatui",
"scopeguard",

View file

@ -27,7 +27,7 @@ bitflags = { workspace = true }
crossterm = { workspace = true }
dirs = { workspace = true }
futures = { workspace = true }
notify = { package = "notify-fork", version = "6.1.1", default-features = false, features = [ "macos_fsevent" ] }
notify = { version = "7.0.0", default-features = false, features = [ "macos_fsevent" ] }
parking_lot = { workspace = true }
ratatui = { workspace = true }
scopeguard = { workspace = true }

View file

@ -22,7 +22,11 @@ impl FilesSorter {
if self.sensitive {
self.cmp(a.name(), b.name(), self.promote(a, b))
} else {
self.cmp(a.name().to_ascii_uppercase(), b.name().to_ascii_uppercase(), self.promote(a, b))
self.cmp_insensitive(
a.name().as_encoded_bytes(),
b.name().as_encoded_bytes(),
self.promote(a, b),
)
}
};
@ -40,9 +44,9 @@ impl FilesSorter {
let ord = if self.sensitive {
self.cmp(a.url.extension(), b.url.extension(), self.promote(a, b))
} else {
self.cmp(
a.url.extension().map(|s| s.to_ascii_lowercase()),
b.url.extension().map(|s| s.to_ascii_lowercase()),
self.cmp_insensitive(
a.url.extension().map_or(&[], |s| s.as_encoded_bytes()),
b.url.extension().map_or(&[], |s| s.as_encoded_bytes()),
self.promote(a, b),
)
};
@ -99,6 +103,25 @@ impl FilesSorter {
}
}
#[inline(always)]
fn cmp_insensitive(&self, a: &[u8], b: &[u8], promote: Ordering) -> Ordering {
if promote != Ordering::Equal {
return promote;
}
let l = a.len().min(b.len());
let (lhs, rhs) = if self.reverse { (&b[..l], &a[..l]) } else { (&a[..l], &b[..l]) };
for i in 0..l {
match lhs[i].to_ascii_lowercase().cmp(&rhs[i].to_ascii_lowercase()) {
Ordering::Equal => (),
not_eq => return not_eq,
}
}
if self.reverse { b.len().cmp(&a.len()) } else { a.len().cmp(&b.len()) }
}
#[inline(always)]
fn promote(&self, a: &File, b: &File) -> Ordering {
if self.dir_first { b.is_dir().cmp(&a.is_dir()) } else { Ordering::Equal }

View file

@ -29,4 +29,4 @@ tracing = { workspace = true }
libc = { workspace = true }
[target.'cfg(not(target_os = "android"))'.dependencies]
trash = "5.1.1"
trash = "5.2.0"