improvement: index runtime_sort rekey by primary key instead of scanning - #2818
Merged
Merged
Conversation
Pin the two subtle behaviours before optimising: duplicate primary keys rekey to the first matching input record, and nil-keyed records match nothing (including each other). Passes against the current scan-based implementation.
maybe_rekey/4 mapped each of the n sorted records back onto the input with Enum.find, an n x n scan. Since the sorted list is a permutation of the input, Enum.find lands on each position exactly once, making the cost exactly triangular (n(n+1)/2) regardless of sort order. For the common simple-equality primary key, matching is plain term equality over Map.take/2, so build a key -> record index once and look up in O(1). Resources whose primary key uses semantic equality (Ash.Type.equal?/3, e.g. ci_string) keep the existing scan.
zachdaniel
approved these changes
Aug 2, 2026
Contributor
|
🚀 Thank you for your contribution! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contributor checklist
Leave anything that you believe does not apply unchecked.
Summary
maybe_rekey/4 mapped each of the n sorted records back onto the input with Enum.find. As the sorted list is a permutation of the input, Enum.find lands on each position exactly once, so the cost is exactly triangular, n(n+1)/2, regardless of sort order.
Performance has been made linear for the common simple-equality primary key case, where matching is plain term equality over Map.take/2, by first building a key -> record index. Primary keys using semantic equality (Ash.Type.equal?/3) keep the existing scan.
The first part of the PR is 'test only'.
The second part refactors maybe_rekey/4 to the indexed form, preserving both of those behaviours.
Evidence
Measured on Ash
main, Elixir 1.20.0 / OTP 27. Each run rekeys a shuffled permutation of N records back onto the input — the shape maybe_rekey/4 sees after every runtime sort — with the before/after outputs asserted equal.The cost
Before: cost quadruples as N doubles. After: linear.