-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
seq
performance is very poor, compared with GNU seq
, when passed positive integer values
#7482
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
Comments
The GNU variant issues buffered writes, 4K chunks. This variant issues writes for every number. I also did have a quick look with perf top to explain the greatly increased user time:
I'm not a rust programmer, so I have no idea how to redo this in this language. :-> Hopefully I did save someone a little bit of digging. |
the perf profile: https://share.firefox.dev/3DM2Bus |
@mjguzik great catch! I wanted to cover the integer case with this issue, but you're totally right, and it does help reducing system time in all cases. Just adding this in
BUT... only when a format is specified! There is still something else going on when printing integers. I tried to cast everything down to
We're still quite a bit slower:
I think there's some clever caching of previously converted values (prefix matching?!), because my simplified version is actually faster for some increments:
|
GNU seq is really buggy; it's pointless to compare the performance. I ran "{seq} 0 1 1000000" on uutils 0.0.29, GNU and my own implementation in C (nothing fancy, just ASCII encoded decimal numbers and no optimisation tricks; -f and -s unsupported) and found the following mean±σ's: With -w I got 258.3 ms, 564.5 ms, and 22.9 ms. Similar with -100 instead of 0. seq 18446744073709551617 -1 18446744073709551614: 431.0 µs with incorrect output, 1,9 ms, and 478.7 µs. |
Err, Since positive integer increment a very common usage (probably the most common usage of seq?), it does seem worth it to optimize the performance... Being 30x slower is a bit too much. |
No, you shouldn't throw in the towel, that's why I gave you comparisons against a non-buggy implementation. uutils's implementation is clearly horribly slow, but don't compare it against GNU because their performance is probably a result of their bugs, and I see no reason you would want to introduce those same bugs just for performance. I don't know what reasonable is. It does work flawlessly with non-negative integers as far as I can tell, but negatives and non-integers is a challenge for it. It does seem to work with smaller negative integers, and but when it gets larger it gets stuck, it skips values, and it even starts at something completely different that specified. A part from test scripts, I don't know any reason you would use seq(1), and in test scripts, why large positive numbers but not large negative numbers? My implementation was consistent 5 to 6 times slower than GNU in the cases GNU performed well. So if you get close to there I would say you have something that's reasonable. I don't really se any point in optimizing seq(1) as much as possible, it's probably not going to pay of in the real world in any noticeable way, but if do want to optimize as much as possible, not count on being able to get on par with GNU. |
Implemented a fast path in #7564. It's quite a bit of added code, but it does provide significant performance benefits, and gets within 10% of the GNU implementation in those cases (and totally beats |
GNU
seq
is a lot faster when passed integer parameters, without format or fixed width options.I suspect there is some very targeted optimization going on for this most common use case, as the gap is not nearly as bad when a format is specified (or
-w
), or when some of the values are negative:The text was updated successfully, but these errors were encountered: