import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.junit.Assert.assertFalse; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import java.util.Set; import org.infinispan.Cache; import org.infinispan.commands.RemoveCacheCommand; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.global.GlobalConfigurationBuilder; import org.infinispan.container.versioning.NumericVersionGenerator; import org.infinispan.container.versioning.NumericVersionGenerator.RankCalculator; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.notifications.cachemanagerlistener.CacheManagerNotifier; import org.infinispan.notifications.cachemanagerlistener.CacheManagerNotifierImpl; import org.junit.Test; /** * This is a test which tries to use Infinispan for a large number of anonymous transient caches. Such caches may live for a very * long time, or a short time, but are generally not given well-known-names so they can be shared with others. Internally we like * to call these "local unshared" caches. *
* There are 3 leaks which prevent this from working. The first two only manifest if {@link Cache#stop()} is called before
* {@link EmbeddedCacheManager#removeCache(String)}, the third always manifests. Using a simple cache does not seem to affect the
* leaks.
*/
public class TransientInfinispanCacheTest {
private static final int MAX_CACHES = 100_000;
private static final int MAX_GC_SECONDS = 5;
private static final int REPORT_INTERVAL = 100;
private static final boolean USE_SIMPLE_CACHE = true; // Seems to have no affect on leaks
private static final boolean USE_CACHE_STOP = true; // Call Cache.stop() before removing?
private static final boolean FIX_LEAK1 = true; // Need if Cache.stop() called first
private static final boolean FIX_LEAK2 = true; // Need if Cache.stop() called first
private static final boolean FIX_LEAK3 = true;
@Test
public void testTransientCacheScaling() throws Throwable {
GlobalConfigurationBuilder globalBuilder = new GlobalConfigurationBuilder();
globalBuilder.globalJmxStatistics().enable();
ConfigurationBuilder builder = new ConfigurationBuilder();
if (USE_SIMPLE_CACHE) {
builder.simpleCache(true);
}
DefaultCacheManager cacheManager = new DefaultCacheManager(globalBuilder.build(), builder.build());
for (int i = 0; i < MAX_CACHES; i++) {
// Progress update...
checkExceededGarbageCollectionTime();
if ((i != 0) && ((i % REPORT_INTERVAL) == 0)) {
System.out.println(i);
}
// Create
String cacheName = "cache" + i; // Unique name
Cache