From d282a1b1cda57adfb49b709bdfeb91bd3b6e8878 Mon Sep 17 00:00:00 2001 From: U000805 Date: Thu, 29 Oct 2026 11:18:02 +0100 Subject: [PATCH] perf: look up case sensitivity without locking ConcurrentHashMap.computeIfAbsent checks only the first node of a bin without locking, so a key that shares a bin with another key locks the bin on every call, even when it is already present. EClasses use identity hash codes, so whether this happens differs from run to run. When it hit a frequently used EClass, the compiler's request workers serialized on that bin while resolving proxies (JDK-8161372). Read the cache with get() first and only call computeIfAbsent on a miss. Also compare case-insensitively first, so that the cache is only consulted for candidate matches rather than for every element of the containment list. --- .../resource/AbstractSelectorFragmentProvider.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/com.avaloq.tools.ddk.xtext/src/com/avaloq/tools/ddk/xtext/resource/AbstractSelectorFragmentProvider.java b/com.avaloq.tools.ddk.xtext/src/com/avaloq/tools/ddk/xtext/resource/AbstractSelectorFragmentProvider.java index 20bb38536d..658c431b8a 100644 --- a/com.avaloq.tools.ddk.xtext/src/com/avaloq/tools/ddk/xtext/resource/AbstractSelectorFragmentProvider.java +++ b/com.avaloq.tools.ddk.xtext/src/com/avaloq/tools/ddk/xtext/resource/AbstractSelectorFragmentProvider.java @@ -125,7 +125,12 @@ public boolean appendFragmentSegment(final EObject object, final StringBuilder b } private static Boolean isCaseSensitive(final EClass eClass) { - return ECLASS_TO_CASE_SENSITIVE.computeIfAbsent(eClass, k -> k.getEAllSuperTypes().stream().map(EClass::getName).anyMatch(n -> "ICaseSensitiveNamedElement".equals(n))); //$NON-NLS-1$ + // computeIfAbsent locks the bin even for a present key unless it is the bin's first node + Boolean caseSensitive = ECLASS_TO_CASE_SENSITIVE.get(eClass); + if (caseSensitive == null) { + caseSensitive = ECLASS_TO_CASE_SENSITIVE.computeIfAbsent(eClass, k -> k.getEAllSuperTypes().stream().map(EClass::getName).anyMatch(n -> "ICaseSensitiveNamedElement".equals(n))); //$NON-NLS-1$ + } + return caseSensitive; } @Override @@ -160,8 +165,8 @@ public EObject getEObjectFromSegment(final EObject container, final String segme return object; } } else { - if ((isCaseSensitive(object.eClass()) ? value.toString().equals(matchedValue) : value.toString().equalsIgnoreCase(matchedValue)) - && index++ == matchedIndex) { + String text = value.toString(); + if (text.equalsIgnoreCase(matchedValue) && (!isCaseSensitive(object.eClass()) || text.equals(matchedValue)) && index++ == matchedIndex) { return object; } }