Skip to content

perf(ui/state): cache lowercase sort key for grouped-process ordering#353

Open
obchain wants to merge 1 commit into
domcyrus:mainfrom
obchain:perf/grouped-sort-cached-key
Open

perf(ui/state): cache lowercase sort key for grouped-process ordering#353
obchain wants to merge 1 commit into
domcyrus:mainfrom
obchain:perf/grouped-sort-cached-key

Conversation

@obchain
Copy link
Copy Markdown
Contributor

@obchain obchain commented May 29, 2026

Summary

compute_grouped_rows sorted process groups with:

group_stats.sort_by_key(|a| a.0.to_lowercase());

slice::sort_by_key does not cache the extracted key — it calls the closure on every comparison, so a merge sort invokes it O(N log N) times. Each call allocates a fresh lowercase String, so sorting N process groups performs ~N·log₂(N) heap allocations where N would do.

compute_grouped_rows runs on every regroup in the Overview grouped view (toggling a, plus refreshes while grouping is active), so this recurs on the update path, not just once.

Switch to slice::sort_by_cached_key, which calls the key function exactly once per element, caches the results, and sorts those. Same key, same ordering — strictly fewer allocations. For 64 process groups that's 64 lowercase Strings per regroup instead of ~384.

Closes #352.

Behavior

No change — identical sort key and comparison. Verified by:

cargo test --lib                          # 379 passed
cargo fmt --check                          # clean
cargo clippy --all-targets -- -D warnings  # clean

Test plan

  • Full cargo test --lib
  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings

`compute_grouped_rows` sorted process groups with:

  group_stats.sort_by_key(|a| a.0.to_lowercase());

`slice::sort_by_key` does not cache the extracted key — it calls the
closure on every comparison, so a merge sort invokes it O(N log N)
times. Each call allocates a fresh lowercase `String`, meaning sorting
N process groups performs ~N·log₂(N) heap allocations where N would do.

`compute_grouped_rows` runs on every regroup in the Overview grouped
view, so this recurs on the update path, not just once.

Switch to `slice::sort_by_cached_key`, which calls the key function
exactly once per element, caches the results, and sorts those. Same key,
same ordering — strictly fewer allocations. For 64 process groups that's
64 lowercase Strings per regroup instead of ~384.

No behavior change; full lib test suite (379) stays green.

Closes domcyrus#352
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.

perf(ui/state): use sort_by_cached_key for grouped-process sort to stop re-allocating the lowercase key per comparison

1 participant