Skip to content

Conversation

@viirya
Copy link
Member

@viirya viirya commented Dec 30, 2025

For negative n values, the function was calling string.chars() twice:

  1. Once to count total characters
  2. Again to take the prefix

This optimization collects chars into a reusable buffer once per row for the negative n case, eliminating the redundant iteration.

Benchmark results (negative n, which triggers the optimization):

  • size=1024: 71.323 µs → 52.760 µs (26.0% faster)
  • size=4096: 289.62 µs → 212.23 µs (26.7% faster)

Benchmark results (positive n, minimal overhead):

  • size=1024: 24.465 µs → 24.691 µs (0.9% slower)
  • size=4096: 96.129 µs → 97.078 µs (1.0% slower)

The dramatic improvement for negative n cases far outweighs the negligible overhead for positive n cases.

Which issue does this PR close?

  • Closes #.

Rationale for this change

What changes are included in this PR?

Are these changes tested?

Are there any user-facing changes?

@github-actions github-actions bot added the functions Changes to functions implementation label Dec 30, 2025
@viirya viirya requested a review from andygrove December 31, 2025 00:50
@adriangb
Copy link
Contributor

Can you make a PR with just the benchmarks (which is easier to merge) so we can then compare main vs. changed?

@viirya
Copy link
Member Author

viirya commented Jan 2, 2026

Opened #19600.

chars_buf.extend(string.chars());
let len = chars_buf.len() as i64;

Some(if n.abs() < len {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor improvement: calling .abs() on MIN will lead to problems (crash in dev and wrapping in release).
i64::MIN is a corner case, so I guess no one will complain that it is not supported here.
I also tried with if n + len > 0 but then it was 3% slower on my machine.

Suggested change
Some(if n.abs() < len {
Some(if n != i64::MIN && n.abs() < len {

For negative n values, the function was calling string.chars() twice:
1. Once to count total characters
2. Again to take the prefix

This optimization collects chars into a reusable buffer once per row
for the negative n case, eliminating the redundant iteration.

Benchmark results (negative n, which triggers the optimization):
- size=1024: 71.323 µs → 52.760 µs  (26.0% faster)
- size=4096: 289.62 µs → 212.23 µs  (26.7% faster)

Benchmark results (positive n, minimal overhead):
- size=1024: 24.465 µs → 24.691 µs  (0.9% slower)
- size=4096: 96.129 µs → 97.078 µs  (1.0% slower)

The dramatic improvement for negative n cases far outweighs the
negligible overhead for positive n cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

functions Changes to functions implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants