-
Notifications
You must be signed in to change notification settings - Fork 444
Description
brief description
0.10.x introduced sysinfo
crate result in very slow speed under Linux.
a simple delta diff cost about 300ms
(with 16 logic core cpu)
Append:
just test on another Linux computer, 6 core CPU
a simple delta diff cost about 100ms
(with 6 logic core cpu)
so for each core, get_cpu_frequency()
call cost about 15ms
, if you CPU core is less than 10, this problem is not easy to found, because you are not very obvious to feel the delay gap.
for any >= 0.10.x version, the more (logic) CPU cores you have, the more slower you get
this issue is also mentioned in #841 (comment)
I also tried delta-0.9.2-x86_64-unknown-linux-gnu (https://github.com/dandavison/delta/releases/download/0.9.2/delta-0.9.2-x86_64-unknown-linux-gnu.tar.gz)
which works without slowdown problem on my machine.
the problem seems to be get_cpu_frequency()
call in sysinfo
crate
my patched version resolved the slowdown problem: https://github.com/ttys3/delta/releases/tag/0.11.2
related commit: ttys3@8f5a835
since this need to patch the sysinfo
crate, it is hard to make a normal
PR -_-
my investigation
here's my env:
------------
OS: Arch Linux x86_64
Kernel: 5.15.6-arch2-1
Shell: zsh 5.8
Resolution: 3840x2160
Terminal: tmux
CPU: Intel i9-9900 (16) @ 5.000GHz
GPU: NVIDIA GeForce GTX 1060 3GB
Memory: 6747MiB / 32038MiB
my git config related to delta:
[pager]
#delta
log = delta --color-only | less -RFX
show = delta --color-only | less -RFX
diff = delta --color-only | less -RFX
1. test with git diff
with delta 0.11.1, do time git diff Cargo.toml
cost about 0.5
s each time (repeated 3 times):
❯ delta --version
delta 0.11.1
git diff Cargo.toml 0.08s user 0.02s system 18% cpu 0.534 total
git diff Cargo.toml 0.07s user 0.04s system 23% cpu 0.505 total
git diff Cargo.toml 0.07s user 0.05s system 20% cpu 0.580 total
with delta 0.11.2, do time git diff Cargo.toml
cost about 0.3
s each time (repeated 3 times):
❯ delta --version
delta 0.11.2
git diff Cargo.toml 0.05s user 0.00s system 18% cpu 0.311 total
git diff Cargo.toml 0.05s user 0.01s system 18% cpu 0.307 total
git diff Cargo.toml 0.04s user 0.02s system 18% cpu 0.305 total
2. without git, run delta directly
time delta Cargo.toml.old Cargo.toml
delta 0.11.1
delta Cargo.toml.old Cargo.toml 0.06s user 0.06s system 20% cpu 0.600 total
delta Cargo.toml.old Cargo.toml 0.06s user 0.06s system 21% cpu 0.567 total
delta Cargo.toml.old Cargo.toml 0.07s user 0.06s system 21% cpu 0.571 total
delta 0.11.2
delta Cargo.toml.old Cargo.toml 0.06s user 0.00s system 18% cpu 0.322 total
delta Cargo.toml.old Cargo.toml 0.06s user 0.01s system 20% cpu 0.311 total
delta Cargo.toml.old Cargo.toml 0.05s user 0.01s system 20% cpu 0.293 total
the result keep the same. so it does not related to git.
the normal speed should be near 0.001s
, just like this (for example time diff Cargo.toml.old Cargo.toml
):
diff --color Cargo.toml.old Cargo.toml 0.00s user 0.00s system 82% cpu 0.001 total
diff --color Cargo.toml.old Cargo.toml 0.00s user 0.00s system 85% cpu 0.001 total
diff --color Cargo.toml.old Cargo.toml 0.00s user 0.00s system 83% cpu 0.001 total
I have found the root cause.
it is delta::utils::process::determine_calling_process
expand the tower top:
so the reason is clear:
delta::utils::process::determine_calling_process
|
V
sysinfo::linux::system::System::refresh_processors
|
v
sysinfo::linux::processor::get_cpu_frequency
oh NO NO NO NO, it try to detect the cpu frequency !!!!
just disable the call, the speed is up:
delta/target/release/delta 0.05s user 0.00s system 101% cpu 0.051 total
delta/target/release/delta 0.05s user 0.01s system 101% cpu 0.051 total
delta/target/release/delta 0.04s user 0.01s system 101% cpu 0.051 total
diff --git a/src/utils/process.rs b/src/utils/process.rs
index 827e44d..ac3a43e 100644
--- a/src/utils/process.rs
+++ b/src/utils/process.rs
@@ -39,7 +39,8 @@ lazy_static! {
}
fn determine_calling_process() -> Option<CallingProcess> {
- calling_process_cmdline(ProcInfo::new(), describe_calling_process)
+ None
+ // calling_process_cmdline(ProcInfo::new(), describe_calling_process)
}
// Return value of `extract_args(args: &[String]) -> ProcessArgs<T>` function which is
the reason is:
delta src/utils/process.rs
Line 230 in a55f021
info: sysinfo::System::new(), |
impl ProcInfo {
fn new() -> Self {
ProcInfo {
info: sysinfo::System::new(),
}
}
}
and sysinfo::System::new()
is:
fn new() -> Self {
Self::new_with_specifics(RefreshKind::new())
}
new_with_specifics
will always try to refresh_processors
:
by default, !refreshes.cpu()
result in !false
, so it is true
:
fn new_with_specifics(refreshes: RefreshKind) -> System {
// ...
if !refreshes.cpu() {
s.refresh_processors(None); // We need the processors to be filled.
}
s.refresh_specifics(refreshes);
// ...
}
there seems no way to forbbide refresh_processors
call.
if we change the new to sysinfo::System::new_with_specifics(sysinfo::RefreshKind::new().with_cpu())
the first s.refresh_processors(None);
will not get called.
but in s.refresh_specifics(refreshes);
, it get called again.