diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/PersistentCacheStatsPerfTest.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/PersistentCacheStatsPerfTest.java new file mode 100644 index 0000000..444a8ee --- /dev/null +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/PersistentCacheStatsPerfTest.java @@ -0,0 +1,313 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.jackrabbit.oak.plugins.document; + +import com.codahale.metrics.Metric; +import com.codahale.metrics.MetricFilter; +import com.codahale.metrics.Slf4jReporter; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheStats; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.MoreExecutors; +import org.apache.commons.io.FileUtils; +import org.apache.jackrabbit.oak.api.CommitFailedException; +import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore; +import org.apache.jackrabbit.oak.plugins.document.persistentCache.CacheType; +import org.apache.jackrabbit.oak.plugins.document.persistentCache.PersistentCache; +import org.apache.jackrabbit.oak.plugins.metric.MetricStatisticsProvider; +import org.apache.jackrabbit.oak.spi.commit.CommitInfo; +import org.apache.jackrabbit.oak.spi.commit.EmptyHook; +import org.apache.jackrabbit.oak.spi.state.NodeBuilder; +import org.apache.jackrabbit.oak.stats.StatisticsProvider; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import javax.management.MBeanServer; +import java.io.File; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.util.HashSet; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * This test + * + * - creates a DocumentNodeStore backed by a MemoryDocumentStore + * + * - populates document node store with 1000 random nodes + * * random node = "/random_node_name" node with 5 random string properties + * + * - PersistentCache wraps a PassthroughCache + * * PassthroughCache = Cache that does not store anything ( Amnesia ) + * * this ensures the values can only be cached by PersistentCache ( not a faster memory cache ) + * + * - readNodesTest + * * read all nodes once ( this will put the nodes into the PersistentCache ) + * * read all nodes NUM_ITERATIONS (default=100.000). these will be served from from PersistentCache + */ +public class PersistentCacheStatsPerfTest { + + private final int NUM_ITERATIONS = Integer.getInteger("numIterations", 100000); + + private final String PERSISTENT_CACHE_PATH = "target/persistent-cache-perf-test"; + + private final Logger LOG = LoggerFactory.getLogger(PersistentCacheStatsPerfTest.class); + + private Set nodePaths; + private Cache cache; + private Cache baseCache; + + private DocumentStore docStore; + private DocumentNodeStore docNodeStore; + + @Rule + public DocumentMKBuilderProvider builderProvider = new DocumentMKBuilderProvider(); + + @Before + public void prepareNodeCache() throws IOException { + + // Create DocumentStore and DocumentNodeStore + docStore = new MemoryDocumentStore(); + docNodeStore = builderProvider + .newBuilder() + .setAsyncDelay(0) + .setDocumentStore(docStore) + .getNodeStore(); + + + // Create StatisticsProvider + Boolean useMetrics = Boolean.getBoolean("enableMetrics"); + StatisticsProvider statisticsProvider; + + if (useMetrics) { + LOG.info("Using Metrics StatisticsProvider"); + statisticsProvider = getMetricsStatisticsProvider(); + } + else { + LOG.info("Using NOOP StatisticsProvider"); + statisticsProvider = StatisticsProvider.NOOP; + } + + // Create clean PersistentCache + FileUtils.deleteDirectory(new File(PERSISTENT_CACHE_PATH)); + PersistentCache pc = new PersistentCache(PERSISTENT_CACHE_PATH); + + // Create NodeCache ( wraps PassthroughCache ) + this.baseCache = new PassthroughCache(); + + // !!! - use next line for PersitentCache with stats + this.cache = pc.wrap(docNodeStore, docStore, baseCache, CacheType.NODE, statisticsProvider); + // !!! - use next line for PersistenceCache without stats + //this.cache = pc.wrap(docNodeStore, docStore, baseCache, CacheType.NODE); + + // Generate some data + this.nodePaths = generateDummyData(); + + } + + @Test + public void readNodesTest() throws Exception{ + + // First iteration will populate the persistent cache + iterateNodes(); + + // Time iterations + long startTime = System.currentTimeMillis(); + + for (int i=0; i generateDummyData() { + Set data = new HashSet(); + Integer numKeys = Integer.getInteger("NUM_KEYS", 1000); + + String child; + NodeBuilder root; + + root = docNodeStore.getRoot().builder(); + for (int i=0; i() { + @Override + public DocumentNodeState call() throws Exception { + DocumentNodeState dns = docNodeStore.readNode(pathStr, rev); + return dns; + } + }); + } + + } + + +} + +class PassthroughCache implements Cache { + + @Nullable + @Override + public V getIfPresent(Object o) { + return null; + } + + @Override + public V get(K k, Callable callable) throws ExecutionException { + try { + return callable.call(); + } catch (Exception e) { + throw new ExecutionException(e); + } + } + + @Override + public ImmutableMap getAllPresent(Iterable iterable) { + return null; + } + + @Override + public void put(K k, V v) { + // do nothing + } + + @Override + public void putAll(Map map) { + // do nothing + } + + @Override + public void invalidate(Object o) { + // do nothing + } + + @Override + public void invalidateAll(Iterable iterable) { + // do nothing + } + + @Override + public void invalidateAll() { + // do nothing + } + + @Override + public long size() { + return 0; + } + + @Override + public CacheStats stats() { + return null; + } + + @Override + public ConcurrentMap asMap() { + return null; + } + + @Override + public void cleanUp() { + } +}