Skip to content

Conversation

drinkcat
Copy link
Collaborator

Gets closer to GNU ls, ~8% gain vs current main.

cargo build -r -p uu_ls && taskset -c 0 hyperfine --warmup 100 -L ls ls,target/release/ls,./ls-main "{ls} -lR /var/lib .git || true"
Benchmark 1: ls -lR /var/lib .git || true
  Time (mean ± σ):      27.2 ms ±   0.6 ms    [User: 11.9 ms, System: 15.0 ms]
  Range (min … max):    26.5 ms …  28.6 ms    109 runs
 
Benchmark 2: target/release/ls -lR /var/lib .git || true
  Time (mean ± σ):      27.9 ms ±   0.9 ms    [User: 12.2 ms, System: 15.2 ms]
  Range (min … max):    26.9 ms …  35.2 ms    104 runs

Benchmark 3: ./ls-main -lR /var/lib .git || true
  Time (mean ± σ):      30.2 ms ±   1.4 ms    [User: 14.2 ms, System: 15.4 ms]
  Range (min … max):    29.3 ms …  42.4 ms    96 runs

Summary
  ls -lR /var/lib .git || true ran
    1.02 ± 0.04 times faster than target/release/ls -lR /var/lib .git || true
    1.11 ± 0.05 times faster than ./ls-main -lR /var/lib .git || true

ls: Optimize time formatting

Instead of recreating the formatter over and over again, keep
it pre-parsed in a variable in TimeStyler class.

Also, avoid calling now over and over again, that's also slow.

Improves performance by about 6%.

ls: display_uname/group: Return a reference

Cache even numerical strings (numeric_uid_gid) in the HashMap,
this makes very little difference performance wise.

However, this allows us to return a reference to a String instead
of making a clone.

Saves about 2-3% on ls -lR /var/lib .git (and ls -lRn).

Also, add a note that HashMap might not be the most optimal choice.

ls: ListState: Add uid/gid cache to the structure

Easier to reason about than the LazyLock/Mutex encapsulated
static variables.

Performance difference is not measurable, but this drops uneeded
Mutex lock/unlock that were seen in samply output.

ls: Create a ListState struct to maintain state

We put the out writer and style manager in there, for now.

Reduces the number of parameters to pass around, and we'll add
more useful things in there.

Little to no performance difference.

We put the out writer and style manager in there, for now.

Reduces the number of parameters to pass around, and we'll add
more useful things in there.

Little to no performance difference.
Easier to reason about than the LazyLock/Mutex encapsulated
static variables.

Performance difference is not measurable, but this drops uneeded
Mutex lock/unlock that were seen in samply output.
Cache even numerical strings (numeric_uid_gid) in the HashMap,
this makes very little difference performance wise.

However, this allows us to return a reference to a String instead
of making a clone.

Saves about 2-3% on `ls -lR /var/lib .git` (and `ls -lRn`).

Also, add a note that HashMap might not be the most optimal choice.
Instead of recreating the formatter over and over again, keep
it pre-parsed in a variable in TimeStyler class.

Also, avoid calling `now` over and over again, that's also slow.

Improves performance by about 6%.
Copy link

GNU testsuite comparison:

GNU test failed: tests/misc/tee. tests/misc/tee is passing on 'main'. Maybe you have to rebase?

@sylvestre sylvestre merged commit 96b7147 into uutils:main Apr 22, 2025
69 of 70 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants