Skip to content

Commit 7be088e

Browse files
committed
Query Quick Access UI providers in a single UI-thread pass
QuickAccessContents computed proposals on a background job but, for every provider that requires UI access, scheduled a separate UIJob and blocked the worker on join(0). With roughly seven UI-access providers (editors, parts, perspectives, commands, actions, preferences, properties) that meant seven serialized worker-to-UI round-trips per keystroke, so the total time to populate the table scaled with UI-thread scheduling latency. Query all UI-access providers together in a single Display.syncExec and look the results up per provider when assembling the table. Non-UI providers still run directly on the worker. A per-provider try/catch keeps one failing provider from aborting the whole pass, matching the previous per-job isolation. Behavior and result ordering are unchanged; only the number of thread hops drops from one-per-provider to one.
1 parent 552c9e4 commit 7be088e

3 files changed

Lines changed: 47 additions & 21 deletions

File tree

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/quickaccess/QuickAccessContents.java

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,45 @@ protected int getNumberOfFilteredResults() {
390390
return numberOfFilteredResults;
391391
}
392392

393+
/**
394+
* Queries every provider that requires UI access in a single UI-thread pass and
395+
* returns their sorted elements keyed by provider. Batching the queries avoids a
396+
* blocking worker-to-UI round-trip per provider on each keystroke.
397+
*/
398+
private Map<QuickAccessProvider, List<QuickAccessElement>> computeUiProviderElements(String filter, String category,
399+
IProgressMonitor monitor) {
400+
List<QuickAccessProvider> uiProviders = new ArrayList<>();
401+
for (QuickAccessProvider provider : providers) {
402+
if (!provider.requiresUiAccess()) {
403+
continue;
404+
}
405+
boolean isPreviousPickProvider = provider instanceof PreviousPicksProvider;
406+
if (category != null && !category.equalsIgnoreCase(provider.getName()) && !isPreviousPickProvider) {
407+
continue;
408+
}
409+
if (!filter.isEmpty() || isPreviousPickProvider || showAllMatches) {
410+
uiProviders.add(provider);
411+
}
412+
}
413+
if (uiProviders.isEmpty() || monitor.isCanceled() || table == null || table.isDisposed()) {
414+
return Collections.emptyMap();
415+
}
416+
Map<QuickAccessProvider, List<QuickAccessElement>> result = new HashMap<>();
417+
table.getDisplay().syncExec(() -> {
418+
for (QuickAccessProvider provider : uiProviders) {
419+
if (monitor.isCanceled()) {
420+
return;
421+
}
422+
try {
423+
result.put(provider, Arrays.asList(provider.getElementsSorted(filter, monitor)));
424+
} catch (RuntimeException e) {
425+
WorkbenchPlugin.log(e);
426+
}
427+
}
428+
});
429+
return result;
430+
}
431+
393432
/**
394433
* Returns a list per provider containing matching {@link QuickAccessEntry} that
395434
* should be displayed in the table given a text filter and a perfect match
@@ -417,6 +456,11 @@ private List<QuickAccessEntry>[] computeMatchingEntries(String filter, QuickAcce
417456
}
418457
final String finalFilter = filter;
419458

459+
// Query providers that must run on the UI thread once, in a single UI pass,
460+
// rather than a separate blocking worker-to-UI round-trip per provider.
461+
Map<QuickAccessProvider, List<QuickAccessElement>> uiProviderElements = computeUiProviderElements(finalFilter,
462+
category, aMonitor);
463+
420464
// collect matching elements
421465
LinkedHashMap<QuickAccessProvider, List<QuickAccessElement>> elementsForProviders = new LinkedHashMap<>(
422466
providers.length);
@@ -430,28 +474,12 @@ private List<QuickAccessEntry>[] computeMatchingEntries(String filter, QuickAcce
430474
continue;
431475
}
432476
if (!filter.isEmpty() || isPreviousPickProvider || showAllMatches) {
433-
AtomicReference<List<QuickAccessElement>> sortedElementRef = new AtomicReference<>();
477+
List<QuickAccessElement> sortedElements;
434478
if (provider.requiresUiAccess()) {
435-
UIJob job = new UIJob(
436-
NLS.bind(QuickAccessMessages.QuickAccessContents_processingProviderInUI,
437-
provider.getName())) {
438-
@Override
439-
public IStatus runInUIThread(IProgressMonitor monitor) {
440-
sortedElementRef.set(Arrays.asList(provider.getElementsSorted(finalFilter, monitor)));
441-
return Status.OK_STATUS;
442-
}
443-
};
444-
job.setPriority(Job.INTERACTIVE);
445-
job.schedule();
446-
try {
447-
job.join(0, new NullProgressMonitor());
448-
} catch (Exception e) {
449-
WorkbenchPlugin.log(e);
450-
}
479+
sortedElements = uiProviderElements.get(provider);
451480
} else {
452-
sortedElementRef.set(Arrays.asList(provider.getElementsSorted(filter, aMonitor)));
481+
sortedElements = Arrays.asList(provider.getElementsSorted(filter, aMonitor));
453482
}
454-
List<QuickAccessElement> sortedElements = sortedElementRef.get();
455483
if (sortedElements == null) {
456484
sortedElements = Collections.emptyList();
457485
}

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/quickaccess/QuickAccessMessages.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ public class QuickAccessMessages extends NLS {
4545
public static String QuickAccessContents_activate;
4646
public static String QuickAccessContents_computeMatchingEntries_displayFeedback_jobName;
4747
public static String QuickaAcessContents_computeMatchingEntries;
48-
public static String QuickAccessContents_processingProviderInUI;
4948

5049
static {
5150
// initialize resource bundle

bundles/org.eclipse.ui.workbench/eclipseui/org/eclipse/ui/internal/quickaccess/messages.properties

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,3 @@ QuickAccessContents_HelpCategory=Help
3535
QuickAccessContents_activate=Activate bundle for ''{0}'' proposals
3636
QuickAccessContents_computeMatchingEntries_displayFeedback_jobName=May show feedback when computing quick access
3737
QuickaAcessContents_computeMatchingEntries=\u23F3 Computing proposals for ''{0}''
38-
QuickAccessContents_processingProviderInUI=Processing ''{0}'' in UI Thread

0 commit comments

Comments
 (0)