From 610d90e10ff997ac43131a579f940ca64340a864 Mon Sep 17 00:00:00 2001 From: Ben Manes Date: Fri, 19 Feb 2016 01:49:06 -0800 Subject: [PATCH] Reduce the jar size by 400kb (codegen) When introducing code generation for the entry and cache, it was overly optimistic and aggressive. That resulted in a larger binary and slow byte code verification. The type hierarchy was optimized and the least useful cases were promoted back to declared references. The CacheLoader reference is another memory optimization that can be rolled back. It should be very commonly used, as we strongly recommend using a self populating cache instead of a manual one. The difference is 14k lines generated (400kb), which is a lot less byte code that might be verified. --- .../benmanes/caffeine/cache/Feature.java | 1 - .../cache/LocalCacheFactoryGenerator.java | 12 +++-- .../cache/LocalCacheSelectorCode.java | 8 ---- .../caffeine/cache/local/AddCacheLoader.java | 45 ------------------- .../caffeine/cache/local/AddConstructor.java | 4 +- .../caffeine/cache/BoundedLocalCache.java | 15 +++---- .../caffeine/cache/AsyncLoadingCacheTest.java | 7 +++ .../caffeine/cache/IsCacheReserializable.java | 2 +- gradle/dependencies.gradle | 2 +- 9 files changed, 22 insertions(+), 74 deletions(-) delete mode 100644 caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddCacheLoader.java diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/Feature.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/Feature.java index fff31a33bf..e46a6f475b 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/Feature.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/Feature.java @@ -44,7 +44,6 @@ public enum Feature { MAXIMUM_WEIGHT, LISTENING, - LOADING, STATS; public static String makeEnumName(Iterable features) { diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheFactoryGenerator.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheFactoryGenerator.java index 4c4208197b..0b66333577 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheFactoryGenerator.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheFactoryGenerator.java @@ -35,7 +35,6 @@ import javax.lang.model.element.Modifier; -import com.github.benmanes.caffeine.cache.local.AddCacheLoader; import com.github.benmanes.caffeine.cache.local.AddConstructor; import com.github.benmanes.caffeine.cache.local.AddDeques; import com.github.benmanes.caffeine.cache.local.AddExpirationTicker; @@ -71,14 +70,14 @@ * @author ben.manes@gmail.com (Ben Manes) */ public final class LocalCacheFactoryGenerator { - final Feature[] featureByIndex = new Feature[] {null, null, Feature.LOADING, Feature.LISTENING, + final Feature[] featureByIndex = new Feature[] {null, null, Feature.LISTENING, Feature.STATS, Feature.MAXIMUM_SIZE, Feature.MAXIMUM_WEIGHT, Feature.EXPIRE_ACCESS, Feature.EXPIRE_WRITE, Feature.REFRESH_WRITE}; final List rules = ImmutableList.of(new AddSubtype(), new AddConstructor(), - new AddKeyValueStrength(), new AddCacheLoader(), new AddRemovalListener(), - new AddStats(), new AddExpirationTicker(), new AddMaximum(), new AddFastPath(), - new AddDeques(), new AddExpireAfterAccess(), new AddExpireAfterWrite(), - new AddRefreshAfterWrite(), new AddWriteQueue(), new Finalize()); + new AddKeyValueStrength(), new AddRemovalListener(), new AddStats(), + new AddExpirationTicker(), new AddMaximum(), new AddFastPath(), new AddDeques(), + new AddExpireAfterAccess(), new AddExpireAfterWrite(), new AddRefreshAfterWrite(), + new AddWriteQueue(), new Finalize()); final NavigableMap> classNameToFeatures; final Path directory; @@ -204,7 +203,6 @@ private static String encode(String className) { .replaceFirst("WEAK_KEYS", "W") .replaceFirst("_STRONG_VALUES", "S") .replaceFirst("_INFIRM_VALUES", "I") - .replaceFirst("_LOADING", "Lo") .replaceFirst("_LISTENING", "Li") .replaceFirst("_STATS", "S") .replaceFirst("_MAXIMUM", "M") diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheSelectorCode.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheSelectorCode.java index e442c9f087..8a694dae13 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheSelectorCode.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheSelectorCode.java @@ -48,13 +48,6 @@ private LocalCacheSelectorCode values() { return this; } - private LocalCacheSelectorCode cacheLoader() { - block.beginControlFlow("if (cacheLoader != null)") - .addStatement("sb.append(\"Lo\")") - .endControlFlow(); - return this; - } - private LocalCacheSelectorCode removalListener() { block.beginControlFlow("if (builder.removalListener != null)") .addStatement("sb.append(\"Li\")") @@ -115,7 +108,6 @@ public static CodeBlock get(Set classNames) { return new LocalCacheSelectorCode() .keys() .values() - .cacheLoader() .removalListener() .stats() .maximum() diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddCacheLoader.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddCacheLoader.java deleted file mode 100644 index b636e42088..0000000000 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddCacheLoader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015 Ben Manes. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.benmanes.caffeine.cache.local; - -import static com.github.benmanes.caffeine.cache.Specifications.CACHE_LOADER; - -import com.github.benmanes.caffeine.cache.Feature; -import com.squareup.javapoet.FieldSpec; -import com.squareup.javapoet.MethodSpec; - -/** - * @author ben.manes@gmail.com (Ben Manes) - */ -public final class AddCacheLoader extends LocalCacheRule { - - @Override - protected boolean applies() { - return context.generateFeatures.contains(Feature.LOADING); - } - - @Override - protected void execute() { - context.constructor.addStatement("this.cacheLoader = cacheLoader"); - context.cache.addField(FieldSpec.builder(CACHE_LOADER, "cacheLoader", - privateFinalModifiers).build()); - context.cache.addMethod(MethodSpec.methodBuilder("cacheLoader") - .addModifiers(protectedFinalModifiers) - .addStatement("return cacheLoader") - .returns(CACHE_LOADER) - .build()); - } -} diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddConstructor.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddConstructor.java index 4725dcfe20..6074565921 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddConstructor.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddConstructor.java @@ -36,8 +36,6 @@ protected void execute() { .addParameter(BUILDER_PARAM) .addParameter(CACHE_LOADER_PARAM) .addParameter(boolean.class, "async") - .addStatement(context.parentFeatures.isEmpty() - ? "super(builder, async)" - : "super(builder, cacheLoader, async)"); + .addStatement("super(builder, (CacheLoader) cacheLoader, async)"); } } diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java index 33dc8f045f..a2f177a0fb 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java @@ -132,6 +132,7 @@ abstract class BoundedLocalCache extends BLCHeader.DrainStatusRef final ConcurrentHashMap> data; final Consumer> accessPolicy; + final CacheLoader cacheLoader; final Buffer> readBuffer; final Runnable drainBuffersTask; final CacheWriter writer; @@ -147,8 +148,10 @@ abstract class BoundedLocalCache extends BLCHeader.DrainStatusRef transient Set> entrySet; /** Creates an instance based on the builder's configuration. */ - protected BoundedLocalCache(Caffeine builder, boolean isAsync) { + protected BoundedLocalCache(Caffeine builder, + @Nullable CacheLoader cacheLoader, boolean isAsync) { this.isAsync = isAsync; + this.cacheLoader = cacheLoader; executor = builder.getExecutor(); writer = builder.getCacheWriter(); weigher = builder.getWeigher(isAsync); @@ -207,10 +210,6 @@ protected Queue writeQueue() { throw new UnsupportedOperationException(); } - protected CacheLoader cacheLoader() { - throw new UnsupportedOperationException(); - } - @Override public final Executor executor() { return executor; @@ -762,7 +761,7 @@ void refreshIfNeeded(Node node, long now) { return v; } try { - return cacheLoader().reload(k, v); + return cacheLoader.reload(k, v); } catch (Exception e) { node.setWriteTime(writeTime); return LocalCache.throwUnchecked(e); @@ -2635,7 +2634,7 @@ static final class BoundedLocalLoadingCache extends BoundedLocalManualCach @Override public CacheLoader cacheLoader() { - return cache.cacheLoader(); + return cache.cacheLoader; } @Override @@ -2659,7 +2658,7 @@ Object writeReplace() { if (cache.refreshAfterWrite()) { proxy.refreshAfterWriteNanos = cache.refreshAfterWriteNanos(); } - proxy.loader = cache.cacheLoader(); + proxy.loader = cache.cacheLoader; return proxy; } } diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncLoadingCacheTest.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncLoadingCacheTest.java index a3c89f0acb..ac8d704a57 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncLoadingCacheTest.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncLoadingCacheTest.java @@ -88,6 +88,13 @@ public void asyncLoadAll() throws Throwable { throw e.getCause(); } } + + @Test + public void asyncReload() throws Exception { + CacheLoader loader = key -> -key; + CompletableFuture future = loader.asyncReload(1, 2, MoreExecutors.directExecutor()); + assertThat(future.get(), is(-1)); + } /* ---------------- getIfPresent -------------- */ diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/IsCacheReserializable.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/IsCacheReserializable.java index 755c547921..4b0d98c2e3 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/IsCacheReserializable.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/IsCacheReserializable.java @@ -196,7 +196,7 @@ private static void checkBoundedLocalManualCache( private static void checkBoundedLocalLoadingCache( BoundedLocalCache.BoundedLocalLoadingCache original, BoundedLocalCache.BoundedLocalLoadingCache copy, DescriptionBuilder desc) { - desc.expectThat("same cacheLoader", copy.cache.cacheLoader(), is(original.cache.cacheLoader())); + desc.expectThat("same cacheLoader", copy.cache.cacheLoader, is(original.cache.cacheLoader)); } private static void checkBoundedAsyncLocalLoadingCache( diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index b450b6587c..4f873f28c0 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -119,7 +119,7 @@ ext { osgi_runtime: [ "org.ops4j.pax.exam:pax-exam-container-native:${test_versions.pax_exam}", "org.ops4j.pax.exam:pax-exam-link-mvn:${test_versions.pax_exam}", - "org.ops4j.pax.url:pax-url-aether:2.4.5", + "org.ops4j.pax.url:pax-url-aether:2.4.6", ], testng: [ dependencies.create("org.testng:testng:${test_versions.testng}") {