-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
seq: Add a print_seq fast path function for integer and positive increments #7564
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
Conversation
GNU testsuite comparison:
|
GNU testsuite comparison:
|
29bafc5
to
01816c7
Compare
GNU testsuite comparison:
|
Scrapped a few more percents:
|
GNU testsuite comparison:
|
(Also added support for constant width printing, it's easy to add) |
GNU testsuite comparison:
|
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.
Excellent! Just some small comments
src/uu/seq/src/seq.rs
Outdated
// Clippy wants to use `if let Some(...) = ...` to avoid is_some/unwrap combination, but that's | ||
// not possible within an "if" test with multiple sub-expressions. | ||
#[allow(clippy::unnecessary_unwrap)] | ||
if fast_allowed && first_bui.is_some() && increment_u64.is_some() && last_bui.is_some() { |
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.
Maybe you could do
if fast_allowed {
// Test if we can use fast code path.
// First try to convert the range to BigUint (u64 for the increment).
let (first_bui, increment_u64, last_bui) = (
first.to_biguint(),
increment.to_biguint().and_then(|x| x.to_u64()),
last.to_biguint(),
);
if let (Some(first_bui), Some(increment_u64), Some(last_bui)) = (first_bui, increment_u64, last_bui) {
...
}
}
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.
Oh! That's better indeed. Thanks!
src/uu/seq/src/seq.rs
Outdated
// Fast code path increment function. | ||
// Add inc to the string val[start..end]. This operates on ASCII digits, assuming | ||
// val and inc are well formed. | ||
// Returns the new value for start. |
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.
You can make this a docstring, which makes it also show up in language servers and things like that.
// Fast code path increment function. | |
// Add inc to the string val[start..end]. This operates on ASCII digits, assuming | |
// val and inc are well formed. | |
// Returns the new value for start. | |
/// Fast code path increment function. | |
/// | |
/// Add inc to the string val[start..end]. This operates on ASCII digits, assuming | |
/// val and inc are well formed. | |
/// Returns the new value for start. |
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.
Done, thanks!
GNU testsuite comparison:
|
…ements A lot of custom logic, we basically do arithmetic on character arrays, but this comes at with huge performance gains. Unlike coreutils `seq`, we do this for all positive increments (because why not), and we do not fall back to slow path if the last parameter is in scientific notation. Also, add some tests for empty separator, as that may catch some corner cases.
It is actually quite easy to implement, we just start with a padded number and increment as usual.
I feel a bit better about this, seeing that some of the extra code can be reused in #7782. We could directly merge that PR and drop this one, either way is fine. |
GNU testsuite comparison:
|
Merged as part of #7782! |
A lot of custom logic, we basically do arithmetic on character arrays, but this comes at with huge performance gains.
Unlike coreutils
seq
, we do this for all positive increments (because why not), and we don't fall back to slow path if the last parameter is in scientific notation.Fixes #7482
I'm not too sure what I think about this ,-) This is a lot of added code, but this comes with huge performance gains, around 17x in some cases (and also, it was a fun puzzle, and I learnt quite a few new Rust things ,-P), and we are now competitive with GNU
seq
:We're less conservative than
GNU
, so this path also activates for ranges likes1 123 100000000
(the GNU manual says they do something special below 200 increment, but I suspect that value is lower) and1e11
, as long as the desired precision is still zero (a.k.a. integers).Still a draft, probably want to add something to
BENCHMARKING.md
, a few more tests, and see if I can extract a bit more performance...