From 6adeeda080a3a14b5663f543c9de1cb7b4d47ef4 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Tue, 21 Jan 2025 10:23:58 +0200 Subject: [PATCH] Remove lambdas from Arc that are used at startup These have a small effect on startup time, so we let's remove them without losing any functionality --- .../impl/ComputingCacheContextInstances.java | 2 +- .../arc/impl/CurrentManagedContext.java | 7 +- .../java/io/quarkus/arc/impl/EventImpl.java | 82 +++++++++++++++---- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ComputingCacheContextInstances.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ComputingCacheContextInstances.java index 89f02ef769030..a821dcf1e430b 100644 --- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ComputingCacheContextInstances.java +++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/ComputingCacheContextInstances.java @@ -37,7 +37,7 @@ public Set> getAllPresent() { @Override public void removeEach(Consumer> action) { if (action != null) { - instances.getPresentValues().forEach(action); + instances.forEachExistingValue(action); } instances.clear(); } diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/CurrentManagedContext.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/CurrentManagedContext.java index 266185912d5a1..ae854f02e8d66 100644 --- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/CurrentManagedContext.java +++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/CurrentManagedContext.java @@ -173,7 +173,12 @@ public void destroy(ContextState state) { CurrentContextState currentState = ((CurrentContextState) state); if (currentState.invalidate()) { fireIfNotNull(beforeDestroyedNotifier); - currentState.contextInstances.removeEach(ContextInstanceHandle::destroy); + currentState.contextInstances.removeEach(new Consumer<>() { + @Override + public void accept(ContextInstanceHandle contextInstanceHandle) { + contextInstanceHandle.destroy(); + } + }); fireIfNotNull(destroyedNotifier); } } else { diff --git a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/EventImpl.java b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/EventImpl.java index fb7fa562013d0..a407d261b58c8 100644 --- a/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/EventImpl.java +++ b/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/EventImpl.java @@ -19,6 +19,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executor; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -122,7 +123,13 @@ private Notifier getNotifier(Class runtimeType) { if (notifier != null && notifier.runtimeType.equals(runtimeType)) { return notifier; } - return this.lastNotifier = notifiers.computeIfAbsent(runtimeType, this::createNotifier); + return this.lastNotifier = notifiers.computeIfAbsent(runtimeType, + new Function<>() { + @Override + public Notifier apply(Class clazz) { + return createNotifier(clazz); + } + }); } @Override @@ -260,7 +267,14 @@ static class Notifier { this.runtimeType = runtimeType; this.observerMethods = observerMethods; this.eventMetadata = eventMetadata; - this.hasTxObservers = observerMethods.stream().anyMatch(this::isTxObserver); + boolean hasTxObservers = false; + for (var method : observerMethods) { + if (isTxObserver(method)) { + hasTxObservers = true; + break; + } + } + this.hasTxObservers = hasTxObservers; this.activateRequestContext = activateRequestContext; } @@ -272,8 +286,8 @@ void notify(T event) { void notify(T event, ObserverExceptionHandler exceptionHandler, boolean async) { if (!isEmpty()) { - Predicate> predicate = async ? ObserverMethod::isAsync - : Predicate.not(ObserverMethod::isAsync); + Predicate> predicate = async ? ObserverMethodIsAsync.INSTANCE + : ObserverMethodIsNotAsync.INSTANCE; if (!async && hasTxObservers) { // Note that tx observers are never async @@ -303,13 +317,13 @@ void notify(T event, ObserverExceptionHandler exceptionHandler, boolean async) { // See for instance discussions on https://github.com/eclipse-ee4j/cdi/issues/467 txManager.getTransaction().registerSynchronization(sync); // registration succeeded, notify all non-tx observers synchronously - predicate = predicate.and(this::isNotTxObserver); + predicate = predicate.and(ObserverMethodIsNotTxObserver.INSTANCE); } catch (Exception e) { if (e.getCause() instanceof RollbackException || e.getCause() instanceof IllegalStateException || e.getCause() instanceof SystemException) { // registration failed, AFTER_SUCCESS OMs are accordingly to CDI spec left out - predicate = predicate.and(this::isNotAfterSuccess); + predicate = predicate.and(ObserverMethodIsNotAfterSuccessTxObserver.INSTANCE); } } } @@ -343,9 +357,9 @@ void notify(T event, ObserverExceptionHandler exceptionHandler, boolean async) { @SuppressWarnings({ "rawtypes", "unchecked" }) private void notifyObservers(T event, ObserverExceptionHandler exceptionHandler, - Predicate> predicate) { + Predicate> predicate) { EventContext eventContext = new EventContextImpl<>(event, eventMetadata); - for (ObserverMethod observerMethod : observerMethods) { + for (ObserverMethod observerMethod : observerMethods) { if (predicate.test(observerMethod)) { try { observerMethod.notify(eventContext); @@ -360,18 +374,10 @@ boolean isEmpty() { return observerMethods.isEmpty(); } - private boolean isTxObserver(ObserverMethod observer) { + private static boolean isTxObserver(ObserverMethod observer) { return !observer.getTransactionPhase().equals(TransactionPhase.IN_PROGRESS); } - private boolean isNotAfterSuccess(ObserverMethod observer) { - return !observer.getTransactionPhase().equals(TransactionPhase.AFTER_SUCCESS); - } - - private boolean isNotTxObserver(ObserverMethod observer) { - return !isTxObserver(observer); - } - } static class ArcSynchronization implements Synchronization { @@ -401,6 +407,48 @@ public void afterCompletion(int i) { } } + private static class ObserverMethodIsAsync implements Predicate> { + + private static final Predicate> INSTANCE = new ObserverMethodIsAsync(); + + @Override + public boolean test(ObserverMethod observerMethod) { + return observerMethod.isAsync(); + } + } + + private static class ObserverMethodIsNotAsync implements Predicate> { + + private static final Predicate> INSTANCE = new ObserverMethodIsNotAsync(); + + @Override + public boolean test(ObserverMethod observerMethod) { + return !observerMethod.isAsync(); + } + } + + private static class ObserverMethodIsNotTxObserver implements Predicate> { + + private static final Predicate> INSTANCE = new ObserverMethodIsNotTxObserver(); + + @Override + public boolean test(ObserverMethod observerMethod) { + return !EventImpl.Notifier.isTxObserver(observerMethod); + } + + } + + private static class ObserverMethodIsNotAfterSuccessTxObserver implements Predicate> { + + private static final Predicate> INSTANCE = new ObserverMethodIsNotAfterSuccessTxObserver(); + + @Override + public boolean test(ObserverMethod observerMethod) { + return !observerMethod.getTransactionPhase().equals(TransactionPhase.AFTER_SUCCESS); + } + + } + @SuppressWarnings("rawtypes") static class DeferredEventNotification implements Runnable {