src/uu/ls/BENCHMARKING.md
ls majorly involves fetching a lot of details (depending upon what details are requested, eg. time/date, inode details, etc) for each path using system calls. Ideally, any system call should be done only once for each of the paths - not adhering to this principle leads to a lot of system call overhead multiplying and bubbling up, especially for recursive ls, therefore it is important to always benchmark multiple scenarios.
ls also prints a lot of information, so optimizing formatting operations is also critical:
format unless required.This is an overview over what was benchmarked, and if you make changes to ls, you are encouraged to check
how performance was affected for the workloads listed below. Feel free to add other workloads to the
list that we should improve / make sure not to regress.
Run cargo build --release before benchmarking after you make a change!
hyperfine --warmup 2 "target/release/coreutils ls -R tree > /dev/null".hyperfine --warmup 2 "target/release/coreutils ls -al -R tree > /dev/null".Hyperfine accepts multiple commands to run and will compare them. To compare performance with GNU ls
duplicate the string you passed to hyperfine but remove the target/release/coreutils bit from it.
Example: hyperfine --warmup 2 "target/release/coreutils ls -al -R tree > /dev/null" becomes
hyperfine --warmup 2 "target/release/coreutils ls -al -R tree > /dev/null" "ls -al -R tree > /dev/null"
(This assumes GNU ls is installed as ls)
This can also be used to compare with version of ls built before your changes to ensure your change does not regress this.
Here is a bash script for doing this comparison:
#!/bin/bash
cargo build --no-default-features --features ls --release
args="$@"
hyperfine "ls $args" "target/release/coreutils ls $args"
Note: No localization is currently implemented. This means that the comparison above is not really fair. We can fix this by setting LC_ALL=C, so GNU ls can ignore localization.
strace -c target/release/coreutils ls -al -R treeWith Cargo Flamegraph you can easily make a flamegraph of ls:
cargo flamegraph --cmd coreutils -- ls [additional parameters]
However, if the -R option is given, the output becomes pretty much useless due to recursion. We can fix this by merging all the direct recursive calls with uniq, below is a bash script that does this.
#!/bin/bash
cargo build --release --no-default-features --features ls
perf record target/release/coreutils ls "$@"
perf script | uniq | inferno-collapse-perf | inferno-flamegraph > flamegraph.svg