Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: simplify CacheApiSettings singleton creation #316

Merged
merged 5 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/
@Slf4j
public final class CacheApiSettings {
private static volatile CacheApiSettings INSTANCE;

private final Map<Class<? extends CacheProvider>, CacheProvider> providers = Collections.synchronizedMap(new IdentityHashMap<>(16));
private final AtomicReference<Class<? extends CacheProvider>> defaultCacheProvider = new AtomicReference<>();

Expand All @@ -38,7 +36,7 @@ public final class CacheApiSettings {
private volatile MisconfigurationPolicy defaultMisconfigurationPolicy = MisconfigurationPolicy.IGNORE;

private CacheApiSettings() {
// restrict instantiation
this.populateProviders();
}

/**
Expand Down Expand Up @@ -102,31 +100,14 @@ public void registerCacheProvider(@NonNull Class<? extends CacheProvider> cacheP
}
}

/**
* @return the cache api settings singleton
*/
@NotNull
public static CacheApiSettings getInstance() {
if (INSTANCE == null) {
synchronized (CacheApiSettings.class) {
if (INSTANCE == null) {
CacheApiSettings cacheApiSettings = new CacheApiSettings();
populateProviders(cacheApiSettings);
INSTANCE = cacheApiSettings;
}
}
}
return INSTANCE;
}

private static void populateProviders(CacheApiSettings cacheApiSettings) {
private void populateProviders() {
log.debug("Xanthic: Registering canonical cache providers from the classpath...");

AtomicInteger registered = new AtomicInteger();
Consumer<String> loadImpl = (providerClass) -> {
try {
Class<? extends CacheProvider> clazz = Class.forName(providerClass).asSubclass(CacheProvider.class);
cacheApiSettings.registerCacheProvider(clazz, null); // lazy, init if needed
registerCacheProvider(clazz, null); // lazy, init if needed
registered.incrementAndGet();
} catch (ClassNotFoundException cx) {
log.trace("Xanthic: Could not find optional cache provider " + providerClass);
Expand All @@ -148,4 +129,16 @@ private static void populateProviders(CacheApiSettings cacheApiSettings) {

log.debug("Xanthic: Loaded {} canonical cache provider(s) on settings construction!", registered.get());
}

/**
* @return the cache api settings singleton
*/
@NotNull
public static CacheApiSettings getInstance() {
return SingletonHolder.INSTANCE;
}

private static class SingletonHolder {
private static final CacheApiSettings INSTANCE = new CacheApiSettings();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import static org.junit.jupiter.api.Assertions.assertThrows;

Expand All @@ -23,10 +26,19 @@ public class CacheRegistrationTest {
@SneakyThrows
void beforeEachTest() {
// reset cache settings singleton
Field instanceField = CacheApiSettings.class.getDeclaredField("INSTANCE");
instanceField.setAccessible(true);
instanceField.set(null, null);
CacheApiSettings.getInstance();
CacheApiSettings instance = CacheApiSettings.getInstance();

Field providers = CacheApiSettings.class.getDeclaredField("providers");
providers.setAccessible(true);
((Map<?, ?>) providers.get(instance)).clear();

Field defaultProvider = CacheApiSettings.class.getDeclaredField("defaultCacheProvider");
defaultProvider.setAccessible(true);
((AtomicReference<?>) defaultProvider.get(instance)).set(null);

Method populate = CacheApiSettings.class.getDeclaredMethod("populateProviders");
populate.setAccessible(true);
populate.invoke(instance);
}

@Test
Expand Down