Skip to content

Conversation

@anastygnome
Copy link
Contributor

This PR is a WIP to get more performance out of tsort.

Move to usize is complete. Next step is to move to vec instead of hashmap

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 26, 2025

CodSpeed Performance Report

Merging #9872 will degrade performance by 5.29%

Comparing anastygnome:tsort (4420344) with main (84e6f03)

Summary

⚡ 1 improvement
❌ 1 regression
✅ 128 untouched
⏩ 30 skipped1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark BASE HEAD Efficiency
tsort_input_parsing_heavy[5000] 84.2 ms 71.9 ms +17.13%
tsort_linear_chain[1000000] 1.5 s 1.6 s -5.29%

Footnotes

  1. 30 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions
Copy link

GNU testsuite comparison:

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

@anastygnome anastygnome force-pushed the tsort branch 3 times, most recently from 81ece9b to 0a56fe6 Compare December 27, 2025 21:48
@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/cp/cp-mv-enotsup-xattr. tests/cp/cp-mv-enotsup-xattr is passing on 'main'. Maybe you have to rebase?
Note: The gnu test tests/csplit/csplit-io-err was skipped on 'main' but is now failing.

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/follow-name is no longer failing!

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/follow-name is no longer failing!

@anastygnome anastygnome force-pushed the tsort branch 2 times, most recently from ddb2361 to b98950c Compare December 27, 2025 23:43
@github-actions
Copy link

GNU testsuite comparison:

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

@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/cp/cp-mv-enotsup-xattr. tests/cp/cp-mv-enotsup-xattr is passing on 'main'. Maybe you have to rebase?
Note: The gnu test tests/csplit/csplit-io-err was skipped on 'main' but is now failing.

@sylvestre
Copy link
Contributor

any idea why the perf regressed here?

@anastygnome
Copy link
Contributor Author

Oh, @sylvestre , I just added a few changes :)
The perf regression is most likely due to using Usize symbols. U32 actually improves performance.

@github-actions
Copy link

GNU testsuite comparison:

GNU test failed: tests/sort/sort-stale-thread-mem. tests/sort/sort-stale-thread-mem is passing on 'main'. Maybe you have to rebase?

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/assert is no longer failing!

@anastygnome anastygnome marked this pull request as ready for review December 28, 2025 13:24
@anastygnome
Copy link
Contributor Author

@sylvestre I believe the regression noticed are due to cache misses because the metadata that goes with the token is just slightly bigger than usize.

Here's another benchmark that maybe of interest:

graph.tsort, 1 Gb random graph 
Massif output: 
Gnu tsort: 

    MB (Memory)
248.6^                                                                       #
     |                                                          ::::::::::@::#
     |                                        ::::::::::::::::::: ::: ::::@: #
     |                               :::::@:::: ::::: : ::::: ::: ::: ::::@: #
     |                            @@:: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |                        ::::@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |                     @@::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |                   ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |               ::::::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |              :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |            :::::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |         :::: :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |       :::: : :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |      :: :: : :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |    :::: :: : :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |    : :: :: : :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |   :: :: :: : :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     |   :: :: :: : :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     | @@:: :: :: : :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
     | @ :: :: :: : :::: ::@ ::: :@ :: : :@:: : ::::: : ::::: ::: ::: ::::@: #
   0 +----------------------------------------------------------------------->Gi (Giga Instructions) 
     0                                                                   23.47

Number of snapshots: 56
 Detailed snapshots: [1, 2, 16, 21, 26, 52, 55 (peak)]
 
 
 
uutils tsort 

     MB (Memory)
200.0^                                                                    #   
     |                                @::::@:::::::::::@::::@::::@::::@:::#:  
     |              :::::::::::@::::::@::::@::: :::::: @::::@::::@::::@:::#:  
     |           ::::::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:  
     |         :::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:: 
     |        ::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:: 
     |      @:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |     :@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |     :@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |     :@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |     :@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |     :@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |   @::@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |  :@::@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |  :@::@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |  :@::@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     |  :@::@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     | ::@::@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     | ::@::@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
     | ::@::@:::::: :::::::::::@:::: :@::::@::: :::::: @::::@::::@::::@:::#:::
   0 +----------------------------------------------------------------------->Gi (Giga Instructions) 
     0                                                                   35.83

Number of snapshots: 98
 Detailed snapshots: [3, 6, 24, 31, 37, 50, 51, 52, 62, 72, 82, 91 (peak)]

Hyperfine : 
 
Benchmark 1: target/release/coreutils tsort /home/bench_vm/graph.tsort
  Time (mean ± σ):      6.044 s ±  0.071 s    [User: 5.602 s, System: 0.394 s]
  Range (min … max):    5.974 s …  6.168 s    10 runs
 
Benchmark 2: tsort /home/bench_vm/graph.tsort 
  Time (mean ± σ):      7.115 s ±  0.147 s    [User: 6.738 s, System: 0.328 s]
  Range (min … max):    6.910 s …  7.390 s    10 runs
`
Summary: 'target/release/coreutils tsort /home/bench_vm/graph.tsort'
ran 1.18 ± 0.03 times faster than 'tsort /home/bench_vm/graph.tsort'
 `

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/assert is no longer failing!

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tty/tty-eof is no longer failing!

@anastygnome anastygnome force-pushed the tsort branch 2 times, most recently from 7e7fa49 to 8c49b1a Compare January 1, 2026 17:02
@github-actions
Copy link

github-actions bot commented Jan 1, 2026

GNU testsuite comparison:

GNU test failed: tests/shuf/shuf-reservoir. tests/shuf/shuf-reservoir is passing on 'main'. Maybe you have to rebase?
GNU test failed: tests/sort/sort-stale-thread-mem. tests/sort/sort-stale-thread-mem is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@anastygnome anastygnome force-pushed the tsort branch 6 times, most recently from 756b865 to b9604fe Compare January 1, 2026 18:16
@github-actions
Copy link

github-actions bot commented Jan 1, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@anastygnome anastygnome force-pushed the tsort branch 2 times, most recently from 8ac2d2a to 51b542f Compare January 1, 2026 21:07
@sylvestre
Copy link
Contributor

windows fails with:


error[E0308]: mismatched types
  --> src\uu\tsort\src\tsort.rs:80:24
   |
80 |             return Err(TsortError::IsDir(input.to_string_lossy().to_string()));
   |                    --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `UIoError`, found `TsortError`
   |                    |
   |                    arguments to this enum variant are incorrect
   |
help: the type constructed contains `TsortError` due to the type of the argument passed
  --> src\uu\tsort\src\tsort.rs:80:20
   |
80 |             return Err(TsortError::IsDir(input.to_string_lossy().to_string()));
   |                    ^^^^------------------------------------------------------^
   |                        |
   |                        this argument influences the type of `Err`
note: tuple variant defined here
  --> /rustc/8d670b93d40737e1b320fd892c6f169ffa35e49e/library\core\src\result.rs:566:4

@anastygnome anastygnome force-pushed the tsort branch 2 times, most recently from 3cd87f8 to a8a1860 Compare January 1, 2026 21:12
@anastygnome
Copy link
Contributor Author

@sylvestre fixed, the rest of the work will be put in another PR.

@github-actions
Copy link

github-actions bot commented Jan 1, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

1 similar comment
@github-actions
Copy link

github-actions bot commented Jan 1, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@github-actions
Copy link

github-actions bot commented Jan 1, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@anastygnome
Copy link
Contributor Author

@sylvestre done :)

@anastygnome
Copy link
Contributor Author

The performance regression is inevitable here if we want to support the same input range (2^64 -1 unique input tokens). There's also a slight buffering cost at the given bench graph size. We are still way more memory efficient, so I'd still consider it a net positive.

@sylvestre sylvestre merged commit 9086f43 into uutils:main Jan 2, 2026
127 of 129 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