Skip to content

Commit

Permalink
perf: optimize SpringLookup lookup time by caching (#17604)
Browse files Browse the repository at this point in the history
* perf: optimize RouteUtil.resolve method

Cache RoutePathProvider in VaadinContext for faster lookup time in RouteUtil.resolve method.

* perf: optimize SpringLookup lookup time by caching

Cache RoutePathProvider in SpringLookup for faster lookup time especially for RouteUtil#resolve method, but also for all default (and subclasses of default) implementations of services defined in LookupInitializer.getDefaultImplementations().
  • Loading branch information
tltv authored Sep 15, 2023
1 parent 19f21ea commit daecc25
Showing 1 changed file with 40 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -61,15 +62,44 @@ private static class SpringLookup extends LookupImpl {

private final WebApplicationContext context;

private final Map<Class<?>, Object> cachedServices;

private final Map<Class<?>, Boolean> cacheableServices;

private SpringLookup(WebApplicationContext context,
BiFunction<Class<?>, Class<?>, Object> factory,
Map<Class<?>, Collection<Class<?>>> services) {
super(services, factory);
this.context = context;
this.cachedServices = new HashMap<>();
this.cacheableServices = new HashMap<>();
}

private <T> boolean isCacheableService(Class<T> serviceClass) {
return cacheableServices.computeIfAbsent(serviceClass,
key -> LookupInitializer.getDefaultImplementations()
.stream().anyMatch(serviceClass::isAssignableFrom));
}

private <T> T getCachedService(Class<T> serviceClass) {
return serviceClass.cast(cachedServices.get(serviceClass));
}

private <T> void setCachedService(Class<T> serviceClass, T service) {
cachedServices.put(serviceClass, service);
}

@Override
public <T> T lookup(Class<T> serviceClass) {
boolean cacheableService = isCacheableService(serviceClass);

if (cacheableService) {
T cached = getCachedService(serviceClass);
if (cached != null) {
return cached;
}
}

Collection<T> beans = context.getBeansOfType(serviceClass).values();

// Check whether we have service objects instantiated without Spring
Expand All @@ -87,13 +117,19 @@ public <T> T lookup(Class<T> serviceClass) {
allFound.addAll(beans);
allFound.add(service);
}
T lookupResult;
if (allFound.size() == 0) {
return null;
lookupResult = null;
} else if (allFound.size() == 1) {
return allFound.iterator().next();
lookupResult = allFound.iterator().next();
} else {
throw new IllegalStateException(SEVERAL_IMPLS + serviceClass
+ SPI + allFound + ONE_IMPL_REQUIRED);
}
if (cacheableService) {
setCachedService(serviceClass, lookupResult);
}
throw new IllegalStateException(SEVERAL_IMPLS + serviceClass + SPI
+ allFound + ONE_IMPL_REQUIRED);
return lookupResult;
}

@Override
Expand Down

0 comments on commit daecc25

Please sign in to comment.