-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tsort refactoring proposal #5968
Conversation
I think we should keep the gnu ordering. I value compatibility over speed |
The thing is topological ordering isn't unique when it exists in most cases. If you rely on the order of a specific implementation, even an update to gnu can break your workflow. Keeping the same order forces us to implement a solution that's 4x slower. If you switch to rust coreutils and you rely on implementation related details, you're in trouble anyway |
This depends on what that order is. For example, if it attempts to retain the order in which the nodes appear in the source, that would make sense. Could you give some examples of which cases differ from GNU? Also, I'd love to see some benchmarks on this using Edit: I've done a measurement:
Looks like this is not yet yielding the results you were hoping for and you actually made it a bit slower. |
well, the test case with the dependencies is such an example. My implementation sorts the nodes alphabetically before running tsort.
this is still a WIP. I'm trying to get better performance indeed. |
Sure, I've generated the input with this: import random
N = 10000
for i in range(100*N):
a = random.randint(0,N)
b = random.randint(0,N)
if a != b:
print(f"{min(a, b)} {max(a, b)}") |
@tertsdiepraam The code still passes all tests and shows a substantial performance improvement, being up to 3 times faster than the current implementation in almost all cases I have tested. I didn't have the time to document it sadly, put simply, I've used another algorithm that leverages the tree nature of the graph in a better way, ensuring less copies and sorting. I believe we can potentially achieve even greater speed improvements by switching from a BTree to a Red-Black tree. I am currently unable to continue this PR, so I hope someone can reuse my work :) |
8c9306a
to
d8b784b
Compare
Remind me on Tuesday! I'd love to take a look then |
2bcf91b
to
76abc9d
Compare
GNU testsuite comparison:
|
For reference, the proposed code in the first commit is approximately 1.5 times slower than GNU tsort. Benchmark 1: target/release/coreutils tsort terts_10000_seed0
Time (mean ± σ): 763.7 ms ± 12.9 ms [User: 736.1 ms, System: 22.8 ms]
Range (min … max): 742.4 ms … 781.6 ms 10 runs
Benchmark 2: tsort terts_10000_seed0
Time (mean ± σ): 509.4 ms ± 4.2 ms [User: 485.3 ms, System: 21.1 ms]
Range (min … max): 503.0 ms … 514.9 ms 10 runs
Summary
tsort terts_10000_seed0 ran
1.50 ± 0.03 times faster than target/release/coreutils tsort terts_10000_seed0 The last commit is a work in progress and serves as a reference to illustrate that the performance cost is mainly driven by the data structure used for nodes. Switching to a hashmap and some manual sort results in a topological order very close to GNU tsort (though it still fails in some cases). Benchmark 1: target/release/coreutils tsort terts_10000_seed0
Time (mean ± σ): 222.5 ms ± 4.5 ms [User: 202.3 ms, System: 19.0 ms]
Range (min … max): 215.8 ms … 229.7 ms 13 runs
Benchmark 2: tsort terts_10000_seed0
Time (mean ± σ): 511.4 ms ± 6.5 ms [User: 490.1 ms, System: 19.3 ms]
Range (min … max): 500.5 ms … 519.5 ms 10 runs
Summary
target/release/coreutils tsort terts_10000_seed0 ran
2.30 ± 0.05 times faster than tsort terts_10000_seed0 The proposed implementation uses Knuth's Algorithm T (TAOCP vol. 1) for topological sorting. This algorithm works by first listing all nodes and counting how many nodes each one depends on (its predecessors). nodes with no predecessors are added to a queue. We then take the node at the front of the queue, remove it from the graph and append it to the result. Any nodes depending on it have their predecessor count reduced. If any of those nodes now have no predecessors, they are added at the back of the queue. This continues until the whole queue is processed. If any nodes remain with predecessors at the end, it means there's a cycle, which we find with a DFS on the remaining subgraph. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! I think you actually settled on something very close to the current version on main
, but with a much better implementation. Most of my comments are easy to fix I think. The compat is interesting. I bet we can fix this to be more compatible, but we'd have to investigate more.
516ef13
to
42f102e
Compare
3cb012d
to
2355df0
Compare
@tertsdiepraam ding dong! |
Sorry I don't have access to a computer this week. Ill try to look at it soonish |
51bd45c
to
9d227cd
Compare
GNU testsuite comparison:
|
ffbdf45
to
f2f15d7
Compare
@tertsdiepraam Hey there, I've corrected typos & clarified the comments. I'm also working on testing replacing strings with IDs, but that will be for another PR. |
GNU testsuite comparison:
|
@sylvestre Hey there, I would also like your input on this one, given the benchmarks, There is still work to be done on tsort, but I believe this one makes it at least good enough for now. |
GNU testsuite comparison:
|
If Terts is happy, I am happy. Could you please add your benchmark in a BENCHMARKING.md file? |
This commit is a complete rewrite of the tsort util, resulting in a x10 performance improvement BREAKING CHANGE: the order is no longer the same as gnu tsort in some fringe cases.
3adbf08
to
a7633ec
Compare
Hello @sylvestre, I have added the benchmarking routine in the md file. |
Thanks! :) |
This pull request is an attempt to rework the current tsort implementation in order to allow for better performance.
I finally had some time to give it a shot after I mentionned it in #4931 with @tertsdiepraam
It also tries to mimic gnu tsort output.
Please share any suggestions.