Skip to content

sort: apply -d and -i to -V keys - #15650

Open
ozenyunus35 wants to merge 3 commits into
uutils:mainfrom
ozenyunus35:sort-version-dictionary
Open

ozenyunus35 wants to merge 3 commits into
uutils:mainfrom
ozenyunus35:sort-version-dictionary

Conversation

@ozenyunus35

Copy link
Copy Markdown
Contributor

Fixes #15587

-V compared the raw key, so -d and -i were ignored, both globally and per key (-k1dV). The -V comparison now removes the characters that -d/-i ignore before comparing the key as a version. The check uses the same filter_char as the other modes:

printf 'b\n_a\n' | sort -dV
# before: b / _a
# after:  _a / b          (same as GNU 9.12)

printf '0\n\t\n' | sort -c -iV
# before: (nothing, exit 0)
# after:  sort: -:2: disorder: <TAB>     (exit 1, same as GNU 9.12)

filter_key returns the key itself when nothing needs removing. Otherwise it copies the kept bytes into a buffer. The two buffers are thread-local and reused, so a comparison doesn't allocate. Plain -V doesn't go through this path.

I added test_version_sort_dictionary_order_and_ignore_nonprinting (-dV, -k1dV, -k1,1dV, -iV, -c -iV). It fails without the change, and all test_sort and uu_sort tests pass. Compared with GNU 9.12 (LC_ALL=C), 17 combinations on a 400-line file with punctuation, blanks, control and non-ASCII bytes give the same output: -V, -dV, -iV, -k1dV, -k1iV, -k1,1dV, with -s, -r, -u, -c, -b, and -t . -k2dV / -k2,2iV. On main, 5 of 6 -d/-i cases differed. Two combinations still differ, and other PRs cover them: -diV needs -d to override -i (#15643), and -fdV needs -V to fold case (#15468).

Timing with a release build, --parallel=1, on a 500,000-line file of version strings (mean of 7 runs):

  • sort -V: 1.03 s on main, 1.04 s here
  • sort -iV: 1.05 s → 1.15 s
  • sort -dV: 1.03 s → 1.24 s

On main, -iV and -dV didn't filter at all, so they cost the same as -V. My first version allocated a new key on each comparison, and -dV took 1.89 s. With the reused buffers it is 1.24 s. The output on that file is the same as GNU's for -dV and -iV.

I used an AI assistant to help draft parts of the code and tests; I reviewed the changes and ran the tests myself.

-V compared the raw key, so -d and -i were ignored, globally and per key.
Remove the characters they ignore before comparing the key as a version.
The filtered keys go into reused thread-local buffers, and a key is only
copied when something is removed from it.
@codspeed

codspeed Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Merging this PR will degrade performance by 4.68%

2 warnings, 1 note

⚠️ 115 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

ℹ️ 1 benchmark has no flamegraph

The flamegraph wasn't generated: most of the time was spent in runtime internals, which would leave nothing useful to analyze.

See affected benchmarks

❌ 2 regressed benchmarks
✅ 399 untouched benchmarks
⏩ 70 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ CPU Simulation sort_numeric[500000] 2.4 s 2.6 s -6.01%
❌ CPU Simulation sort_general_numeric[200000] 1.4 s 1.5 s -3.33%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing ozenyunus35:sort-version-dictionary (483e9c3) with main (a0df09e)

Open in CodSpeed

Footnotes

  1. 70 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
Copy Markdown

Binary size comparison:

Individual binary size comparison VS main (threshold: >=5% AND >=4 KB).

Total size of compared binaries: 155.04 MB (-304 KB, -0.19%)

Significant per-binary changes:
  date     2.61 MB ->    2.30 MB  (-316 KB, -11.81%)

.stdout_is("0.1\n0.02\n0.2\n0.002\n0.3\n");
}

#[test]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could you use #[rstest] cases?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@xtqqczze Done in 6ce42de.

Comment thread tests/by-util/test_sort.rs Outdated
}

// -d and -i drop characters from the key before it is compared as a version
#[rstest]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

on second thoughts, would this better as four separate tests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@xtqqczze Done in 483e9c3, they're four separate tests now.

This branch has not been deployed

No deployments
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.

sort: -V ignores -d and -i (follow-up to #15463)

2 participants