Skip to content

Look up the displaced action by command id in KeyBindingService - #4243

Open
vogella wants to merge 1 commit into
eclipse-platform:masterfrom
vogella:keybindingservice-registeraction-lookup
Open

Look up the displaced action by command id in KeyBindingService#4243
vogella wants to merge 1 commit into
eclipse-platform:masterfrom
vogella:keybindingservice-registeraction-lookup

Conversation

@vogella

@vogella vogella commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

KeyBindingService.registerAction scanned every already registered action to find the one currently holding the command id it is about to take over. AbstractTextEditor registers dozens of actions per editor via setAction, so registering n actions costs O(n^2) comparisons on every editor open. A map from command id to action, plus its inverse for removal, turns that into a single lookup. As a side effect the scan no longer removes entries from the keySet it is iterating, which previously only avoided a ConcurrentModificationException because of the break immediately after it.

The maps are keyed by the command id an action was registered under rather than by its current definition id. Those differ only when getActionDefinitionId changes after registration, and in that case eviction now matches the id the handler activation actually uses, rather than one the activation was never created for.

The PR also adds KeyBindingServiceTest. Registering an action for an already bound command id displaces the previous action, and the displaced one has to be deactivated rather than shadowed so it does not resurface when the replacement is unregistered. None of that had any coverage before. The tests pass unchanged against the previous implementation, so they document existing behaviour rather than the refactor.

To be upfront about the performance side: this is not a measurable win. Timed with OpenCloseEditorTest over three alternating runs per variant, the difference stays below the run to run spread of the baseline itself. The value here is the removed quadratic loop, the removed iteration hazard, and the new test coverage.

registerAction scanned every already registered action to find the one
holding the command id it is about to take over. AbstractTextEditor
registers dozens of actions per editor through setAction, so registering
n actions cost O(n^2) comparisons on every editor open.

Keep a map from command id to action, and its inverse for removal, so the
lookup is a single map access. The scan also removed entries from the
keySet it was iterating and only avoided a ConcurrentModificationException
because of the break directly after, which the map lookup makes moot.

The maps are keyed by the command id an action was registered under
rather than by its current definition id. These differ only if
getActionDefinitionId changes after registration, in which case eviction
now matches the id the handler activation actually uses instead of one
the activation was never created for.

Add KeyBindingServiceTest, which pins down that registering an action for
an already bound command id displaces the previous action, and that the
displaced action is deactivated rather than shadowed, so it does not
resurface once the replacement is unregistered. That behaviour had no
coverage. The tests pass unchanged against the previous implementation.

This is not a measurable speedup. Timed with OpenCloseEditorTest over
three alternating runs per variant, the difference stays under the
run to run spread of the baseline itself.
@github-actions

Copy link
Copy Markdown
Contributor

Test Results

   858 files  ± 0     858 suites  ±0   48m 43s ⏱️ - 3m 40s
 8 163 tests + 6   7 920 ✅ + 6  243 💤 ±0  0 ❌ ±0 
20 391 runs  +18  19 737 ✅ +18  654 💤 ±0  0 ❌ ±0 

Results for commit e1201e2. ± Comparison against base commit fdcfd9a.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant