perf: use lookup maps instead of linear opponent scans in standings widgets#7649
Open
Rathoz wants to merge 1 commit into
Open
perf: use lookup maps instead of linear opponent scans in standings widgets#7649Rathoz wants to merge 1 commit into
Rathoz wants to merge 1 commit into
Conversation
…idgets Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
90dff66 to
40a92a9
Compare
hjpalpha
approved these changes
Jun 12, 2026
hjpalpha
left a comment
Collaborator
There was a problem hiding this comment.
lgtm on phone
fwiw it will make salts goal to allow A/B teams stuff harder
Collaborator
I'm currently convinced we'd need to support them inside Opponent.toName anyways (as other components, i.e. TeamParticipants use that), so the effect of this is probably not that bad. |
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.
Summary
Opponent.sameinside a per-cell nested loop to find an opponent's entry in each column round, producing O(R²·N²)Opponent.samecalls per render. The Swiss widget had the same pattern at O(R·N²).Opponent.sameis expensive: it can invoke uncachedmw.ext.TeamTemplate.rawPHP callbacks for team opponents, or allocate and sort arrays for party opponents.entryByRoundtable once per standings render: an array (one entry per round) of{ [Opponent.toName(entry.opponent)] = entry }maps.Opponent.toNamereturns a stable identity string (no PHP calls, no allocation). The per-cell lookup becomes a plain O(1) table access, andOpponent.toName(slot.opponent)is hoisted out of each row's per-column closure so it is computed once per row rather than once per column.toNamekeys are consistent across rounds — no fallback needed for entry lookups.Array.indexOf(match.opponents, …)call inside the Swiss per-cell body (which identifies the opposing player in a 2-opponent match) is deliberately left onOpponent.same: those opponents come from match2 records where renamed-team handling inOpponent.samematters, and it is only ever called on 2 opponents per match, so it is not a performance concern.How did you test this change?
busted --run=ci(full suite): 605 successes / 0 failures / 0 errors — includingspec/standings_model_spec.lua, which renders both the FFA and Swiss widgets end-to-end and asserts row ordering and cell content.luacheckon both modified files: 0 warnings / 0 errors.standings-tests-ai(PR test: add integration tests for standings #7647), which adds the widget render tests that lock the behavior being preserved here.🤖 Generated with Claude Code