// Copyright 2017 JanusGraph Authors // // 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 org.janusgraph.graphdb; import com.codahale.metrics.Counter; import com.codahale.metrics.MetricFilter; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Iterators; import org.janusgraph.core.*; import org.janusgraph.core.attribute.Cmp; import org.janusgraph.core.schema.ConsistencyModifier; import org.janusgraph.core.schema.JanusGraphIndex; import static org.janusgraph.diskstorage.Backend.*; import org.janusgraph.diskstorage.configuration.BasicConfiguration; import org.janusgraph.diskstorage.configuration.ModifiableConfiguration; import org.janusgraph.diskstorage.configuration.WriteConfiguration; import org.janusgraph.diskstorage.util.CacheMetricsAction; import org.janusgraph.diskstorage.util.MetricInstrumentedStore; import static org.janusgraph.diskstorage.util.MetricInstrumentedStore.*; import org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration; import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.*; import static org.janusgraph.graphdb.database.cache.MetricInstrumentedSchemaCache.*; import static org.janusgraph.testutil.JanusGraphAssert.assertCount; import static org.junit.Assert.*; import static org.junit.Assert.assertEquals; import org.janusgraph.graphdb.internal.ElementCategory; import org.janusgraph.graphdb.internal.InternalRelationType; import org.janusgraph.graphdb.internal.InternalVertexLabel; import org.janusgraph.graphdb.types.CompositeIndexType; import org.janusgraph.graphdb.types.IndexType; import org.janusgraph.testcategory.SerialTests; import org.janusgraph.util.stats.MetricManager; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.junit.Test; import org.junit.experimental.categories.Category; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** * @author Matthias Broecheler (me@matthiasb.com) */ @Category({ SerialTests.class }) public abstract class JanusGraphOperationCountingTest extends JanusGraphBaseTest { public MetricManager metric; public final String SYSTEM_METRICS = GraphDatabaseConfiguration.METRICS_SYSTEM_PREFIX_DEFAULT; public abstract WriteConfiguration getBaseConfiguration(); public final boolean storeUsesConsistentKeyLocker() { return !this.features.hasLocking(); } @Override public WriteConfiguration getConfiguration() { WriteConfiguration config = getBaseConfiguration(); ModifiableConfiguration mconf = new ModifiableConfiguration(GraphDatabaseConfiguration.ROOT_NS,config, BasicConfiguration.Restriction.NONE); mconf.set(BASIC_METRICS,true); mconf.set(METRICS_MERGE_STORES,false); mconf.set(PROPERTY_PREFETCHING,false); mconf.set(DB_CACHE, false); return config; } @Override public void open(WriteConfiguration config) { metric = MetricManager.INSTANCE; super.open(config); } private void verifyLockingOverwrite(String storeName, long num) { if (storeUsesConsistentKeyLocker()) { verifyStoreMetrics(storeName, ImmutableMap.of(M_GET_SLICE, 2*num)); verifyStoreMetrics(storeName+LOCK_STORE_SUFFIX, ImmutableMap.of(M_GET_SLICE, num, M_MUTATE, 2*num)); } else { verifyStoreMetrics(storeName, ImmutableMap.of(M_GET_SLICE, num, M_ACQUIRE_LOCK, num)); } } @Test public void testIdCounts() { makeVertexIndexedUniqueKey("uid", Integer.class); mgmt.setConsistency(mgmt.getGraphIndex("uid"), ConsistencyModifier.LOCK); finishSchema(); //Schema and relation id pools are tapped, Schema id pool twice because the renew is triggered. Each id acquisition requires 1 mutations and 2 reads verifyStoreMetrics(ID_STORE_NAME, SYSTEM_METRICS, ImmutableMap.of(M_MUTATE, 3l, M_GET_SLICE, 6l)); } @Test public void testReadOperations() { testReadOperations(false); } @Test public void testReadOperationsWithCache() { testReadOperations(true); } @SuppressWarnings("unchecked") public void testReadOperations(boolean cache) { metricsPrefix = "testReadOperations"+cache; resetEdgeCacheCounts(); makeVertexIndexedUniqueKey("uid", Integer.class); mgmt.setConsistency(mgmt.getGraphIndex("uid"),ConsistencyModifier.LOCK); finishSchema(); if (cache) clopen(option(DB_CACHE),true,option(DB_CACHE_CLEAN_WAIT),0,option(DB_CACHE_TIME),0); else clopen(); JanusGraphTransaction tx = graph.buildTransaction().groupName(metricsPrefix).start(); tx.makePropertyKey("name").dataType(String.class).make(); tx.makeEdgeLabel("knows").make(); tx.makeVertexLabel("person").make(); tx.commit(); verifyStoreMetrics(EDGESTORE_NAME); verifyLockingOverwrite(INDEXSTORE_NAME, 3); verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 1l)); resetMetrics(); metricsPrefix=GraphDatabaseConfiguration.METRICS_SCHEMA_PREFIX_DEFAULT; resetMetrics(); //Test schema caching for (int t=0;t<10;t++) { tx = graph.buildTransaction().groupName(metricsPrefix).start(); //Retrieve name by index (one backend call each) assertTrue(tx.containsRelationType("name")); assertTrue(tx.containsRelationType("knows")); assertTrue(tx.containsVertexLabel("person")); PropertyKey name = tx.getPropertyKey("name"); EdgeLabel knows = tx.getEdgeLabel("knows"); VertexLabel person = tx.getVertexLabel("person"); PropertyKey uid = tx.getPropertyKey("uid"); //Retrieve name as property (one backend call each) assertEquals("name",name.name()); assertEquals("knows",knows.name()); assertEquals("person",person.name()); assertEquals("uid",uid.name()); //Looking up the definition (one backend call each) assertEquals(Cardinality.SINGLE,name.cardinality()); assertEquals(Multiplicity.MULTI,knows.multiplicity()); assertFalse(person.isPartitioned()); assertEquals(Integer.class,uid.dataType()); //Retrieving in and out relations for the relation types... InternalRelationType namei = (InternalRelationType)name; InternalRelationType knowsi = (InternalRelationType)knows; InternalRelationType uidi = (InternalRelationType)uid; assertNull(namei.getBaseType()); assertNull(knowsi.getBaseType()); IndexType index = Iterables.getOnlyElement(uidi.getKeyIndexes()); assertEquals(1,index.getFieldKeys().length); assertEquals(ElementCategory.VERTEX,index.getElement()); assertEquals(ConsistencyModifier.LOCK,((CompositeIndexType)index).getConsistencyModifier()); assertEquals(1, Iterables.size(uidi.getRelationIndexes())); assertEquals(1, Iterables.size(namei.getRelationIndexes())); assertEquals(namei, Iterables.getOnlyElement(namei.getRelationIndexes())); assertEquals(knowsi, Iterables.getOnlyElement(knowsi.getRelationIndexes())); //.. and vertex labels assertEquals(0,((InternalVertexLabel)person).getTTL()); tx.commit(); //Needs to read on first iteration, after that it doesn't change anymore verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 19l)); verifyStoreMetrics(INDEXSTORE_NAME, ImmutableMap.of(M_GET_SLICE, 4l /* name, knows, person, uid */, M_ACQUIRE_LOCK, 0l)); } //Create some graph data metricsPrefix = "add"+cache; tx = graph.buildTransaction().groupName(metricsPrefix).start(); JanusGraphVertex v = tx.addVertex(), u = tx.addVertex("person"); v.property(VertexProperty.Cardinality.single, "uid", 1); u.property(VertexProperty.Cardinality.single, "name", "juju"); Edge e = v.addEdge("knows",u); e.property("name", "edge"); tx.commit(); verifyStoreMetrics(EDGESTORE_NAME); verifyLockingOverwrite(INDEXSTORE_NAME, 1); for (int i = 1; i <= 30; i++) { metricsPrefix = "op"+i+cache; tx = graph.buildTransaction().groupName(metricsPrefix).start(); v = (JanusGraphVertex)getOnlyElement(tx.query().has("uid",1).vertices()); assertEquals(1,v.<Integer>value("uid").intValue()); u = (JanusGraphVertex)getOnlyElement(v.query().direction(Direction.BOTH).labels("knows").vertices()); e = (Edge)getOnlyElement(u.query().direction(Direction.IN).labels("knows").edges()); assertEquals("juju",u.value("name")); assertEquals("edge",e.value("name")); tx.commit(); if (!cache || i==0) { verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 4l)); verifyStoreMetrics(INDEXSTORE_NAME, ImmutableMap.of(M_GET_SLICE, 1l)); } else if (cache && i>20) { //Needs a couple of iterations for cache to be cleaned verifyStoreMetrics(EDGESTORE_NAME); verifyStoreMetrics(INDEXSTORE_NAME); } } } @Test public void testSettingProperty() throws Exception { metricsPrefix = "testSettingProperty"; mgmt.makePropertyKey("foo").dataType(String.class).cardinality(Cardinality.SINGLE).make(); finishSchema(); JanusGraphVertex v = tx.addVertex(); v.property("foo","bar"); tx.commit(); JanusGraphTransaction tx = graph.buildTransaction().checkExternalVertexExistence(false).groupName(metricsPrefix).start(); v = tx.getVertex(v.longId()); v.property("foo", "bus"); // printAllMetrics(); tx.commit(); verifyStoreMetrics(EDGESTORE_NAME); verifyStoreMetrics(INDEXSTORE_NAME); verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 1l)); tx = graph.buildTransaction().checkExternalVertexExistence(false).groupName(metricsPrefix).start(); v = tx.getVertex(v.longId()); v.property("foo", "band"); assertEquals("band", v.property("foo").value()); assertEquals(1, Iterators.size(v.properties("foo"))); assertEquals(1, Iterators.size(v.properties())); tx.commit(); verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 2l)); verifyStoreMetrics(INDEXSTORE_NAME); verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 2l)); verifyStoreMetrics(ID_STORE_NAME); } @Test public void testKCVSAccess1() throws InterruptedException { metricsPrefix = "testKCVSAccess1"; JanusGraphTransaction tx = graph.buildTransaction().groupName(metricsPrefix).start(); JanusGraphVertex v = tx.addVertex("age", 25, "name", "john"); JanusGraphVertex u = tx.addVertex("age", 35, "name", "mary"); v.addEdge("knows", u); tx.commit(); verifyStoreMetrics(EDGESTORE_NAME); verifyLockingOverwrite(INDEXSTORE_NAME, 3); verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 1l + (features.hasTxIsolation()?0:1))); verifyTypeCacheMetrics(3, 0); //Check type name & definition caching tx = graph.buildTransaction().groupName(metricsPrefix).start(); v = getV(tx,v); assertCount(2, v.properties()); verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 2l)); //1 verify vertex existence, 1 for query verifyTypeCacheMetrics(3, 4); tx.commit(); tx = graph.buildTransaction().groupName(metricsPrefix).start(); v = getV(tx,v); assertCount(2, v.properties()); verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 4l)); //1 verify vertex existence, 1 for query verifyTypeCacheMetrics(3, 4); tx.commit(); //Check type index lookup caching tx = graph.buildTransaction().groupName(metricsPrefix).start(); v = getV(tx,v); assertNotNull(v.value("age")); assertNotNull(v.value("name")); verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 7l)); //1 verify vertex existence, 2 for query verifyTypeCacheMetrics(5, 8); tx.commit(); tx = graph.buildTransaction().groupName(metricsPrefix).start(); v = getV(tx,v); assertNotNull(v.value("age")); assertNotNull(v.value("name")); assertCount(1, v.query().direction(Direction.BOTH).edges()); verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 11l)); //1 verify vertex existence, 3 for query verifyTypeCacheMetrics(5, 10); tx.commit(); verifyLockingOverwrite(INDEXSTORE_NAME, 3); verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 1l + (features.hasTxIsolation()?0:1))); } @Test public void checkPropertyLockingAndIndex() { PropertyKey uid = makeKey("uid",String.class); JanusGraphIndex index = mgmt.buildIndex("uid",Vertex.class).unique().addKey(uid).buildCompositeIndex(); mgmt.setConsistency(index, ConsistencyModifier.LOCK); mgmt.makePropertyKey("name").dataType(String.class).make(); mgmt.makePropertyKey("age").dataType(Integer.class).make(); finishSchema(); metricsPrefix = "checkPropertyLockingAndIndex"; JanusGraphTransaction tx = graph.buildTransaction().groupName(metricsPrefix).start(); JanusGraphVertex v = tx.addVertex("uid", "v1", "age", 25, "name", "john"); assertEquals(25,v.property("age").value()); tx.commit(); verifyStoreMetrics(EDGESTORE_NAME); verifyLockingOverwrite(INDEXSTORE_NAME, 1); verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 1l)); resetMetrics(); tx = graph.buildTransaction().groupName(metricsPrefix).start(); v = (JanusGraphVertex) Iterables.getOnlyElement(tx.query().has("uid", Cmp.EQUAL, "v1").vertices()); assertEquals(25,v.property("age").value()); tx.commit(); verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE,1l)); verifyStoreMetrics(INDEXSTORE_NAME, ImmutableMap.of(M_GET_SLICE,1l)); verifyStoreMetrics(METRICS_STOREMANAGER_NAME); } @Test public void checkFastPropertyTrue() { checkFastProperty(true); } @Test public void checkFastPropertyFalse() { checkFastProperty(false); } public void checkFastProperty(boolean fastProperty) { makeKey("uid",String.class); makeKey("name", String.class); makeKey("age", String.class); finishSchema(); clopen(option(GraphDatabaseConfiguration.PROPERTY_PREFETCHING), fastProperty); metricsPrefix = "checkFastProperty"+fastProperty; JanusGraphTransaction tx = graph.buildTransaction().groupName(metricsPrefix).start(); JanusGraphVertex v = tx.addVertex("uid", "v1", "age", 25, "name", "john"); tx.commit(); verifyStoreMetrics(EDGESTORE_NAME); verifyStoreMetrics(INDEXSTORE_NAME); verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 1l)); tx = graph.buildTransaction().groupName(metricsPrefix).start(); v = getV(tx, v); assertEquals("v1",v.property("uid").value()); assertEquals("25",v.property("age").value()); assertEquals("john",v.property("name").value()); tx.commit(); if (fastProperty) verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 2l)); else verifyStoreMetrics(EDGESTORE_NAME, ImmutableMap.of(M_GET_SLICE, 4l)); verifyStoreMetrics(INDEXSTORE_NAME); verifyStoreMetrics(METRICS_STOREMANAGER_NAME, ImmutableMap.of(M_MUTATE, 1l)); } private String metricsPrefix; public void verifyStoreMetrics(String storeName) { verifyStoreMetrics(storeName, new HashMap<String, Long>(0)); } public void verifyStoreMetrics(String storeName, Map<String, Long> operationCounts) { verifyStoreMetrics(storeName, metricsPrefix, operationCounts); } public void verifyStoreMetrics(String storeName, String prefix, Map<String, Long> operationCounts) { for (String operation : OPERATION_NAMES) { Long count = operationCounts.get(operation); if (count==null) count = 0l; assertEquals(Joiner.on(".").join(prefix, storeName, operation, MetricInstrumentedStore.M_CALLS),count.longValue(), metric.getCounter(prefix, storeName, operation, MetricInstrumentedStore.M_CALLS).getCount()); } } public void verifyTypeCacheMetrics(int nameMisses, int relationMisses) { verifyTypeCacheMetrics(metricsPrefix,nameMisses,relationMisses); } public void verifyTypeCacheMetrics(String prefix, int nameMisses, int relationMisses) { // assertEquals("On type cache name retrievals",nameRetrievals, metric.getCounter(GraphDatabaseConfiguration.METRICS_SYSTEM_PREFIX_DEFAULT, METRICS_NAME, METRICS_TYPENAME, CacheMetricsAction.RETRIEVAL.getName()).getCount()); assertEquals("On type cache name misses",nameMisses, metric.getCounter(GraphDatabaseConfiguration.METRICS_SYSTEM_PREFIX_DEFAULT, METRICS_NAME, METRICS_TYPENAME, CacheMetricsAction.MISS.getName()).getCount()); assertTrue(nameMisses <= metric.getCounter(GraphDatabaseConfiguration.METRICS_SYSTEM_PREFIX_DEFAULT, METRICS_NAME, METRICS_TYPENAME, CacheMetricsAction.RETRIEVAL.getName()).getCount()); // assertEquals("On type cache relation retrievals",relationRetrievals, metric.getCounter(GraphDatabaseConfiguration.METRICS_SYSTEM_PREFIX_DEFAULT, METRICS_NAME, METRICS_RELATIONS, CacheMetricsAction.RETRIEVAL.getName()).getCount()); assertEquals("On type cache relation misses", relationMisses, metric.getCounter(GraphDatabaseConfiguration.METRICS_SYSTEM_PREFIX_DEFAULT, METRICS_NAME, METRICS_RELATIONS, CacheMetricsAction.MISS.getName()).getCount()); assertTrue(relationMisses <= metric.getCounter(GraphDatabaseConfiguration.METRICS_SYSTEM_PREFIX_DEFAULT, METRICS_NAME, METRICS_RELATIONS, CacheMetricsAction.RETRIEVAL.getName()).getCount()); } // public void verifyCacheMetrics(String storeName) { // verifyCacheMetrics(storeName,0,0); // } // // public void verifyCacheMetrics(String storeName, int misses, int retrievals) { // verifyCacheMetrics(storeName, metricsPrefix, misses, retrievals); // } // // public void verifyCacheMetrics(String storeName, String prefix, int misses, int retrievals) { // assertEquals("On "+storeName+"-cache retrievals",retrievals, metric.getCounter(prefix, storeName + Backend.METRICS_CACHE_SUFFIX, CacheMetricsAction.RETRIEVAL.getName()).getCount()); // assertEquals("On "+storeName+"-cache misses",misses, metric.getCounter(prefix, storeName + Backend.METRICS_CACHE_SUFFIX, CacheMetricsAction.MISS.getName()).getCount()); // } public void printAllMetrics() { printAllMetrics(metricsPrefix); } public void printAllMetrics(String prefix) { List<String> storeNames = new ArrayList<>(); storeNames.add(EDGESTORE_NAME); storeNames.add(INDEXSTORE_NAME); storeNames.add(ID_STORE_NAME); storeNames.add(METRICS_STOREMANAGER_NAME); if (storeUsesConsistentKeyLocker()) { storeNames.add(EDGESTORE_NAME+LOCK_STORE_SUFFIX); storeNames.add(INDEXSTORE_NAME+LOCK_STORE_SUFFIX); } for (String store : storeNames) { System.out.println("######## Store: " + store + " (" + prefix + ")"); for (String operation : MetricInstrumentedStore.OPERATION_NAMES) { System.out.println("-- Operation: " + operation); System.out.print("\t"); System.out.println(metric.getCounter(prefix, store, operation, MetricInstrumentedStore.M_CALLS).getCount()); System.out.print("\t"); System.out.println(metric.getTimer(prefix, store, operation, MetricInstrumentedStore.M_TIME).getMeanRate()); if (operation==MetricInstrumentedStore.M_GET_SLICE) { System.out.print("\t"); System.out.println(metric.getCounter(prefix, store, operation, MetricInstrumentedStore.M_ENTRIES_COUNT).getCount()); } } } } @Test public void testCacheConcurrency() throws InterruptedException { metricsPrefix = "tCC"; Object[] newConfig = {option(GraphDatabaseConfiguration.DB_CACHE),true, option(GraphDatabaseConfiguration.DB_CACHE_TIME),0, option(GraphDatabaseConfiguration.DB_CACHE_CLEAN_WAIT),0, option(GraphDatabaseConfiguration.DB_CACHE_SIZE),0.25, option(GraphDatabaseConfiguration.BASIC_METRICS),true, option(GraphDatabaseConfiguration.METRICS_MERGE_STORES),false, option(GraphDatabaseConfiguration.METRICS_PREFIX),metricsPrefix}; clopen(newConfig); final String prop = "someProp"; makeKey(prop,Integer.class); finishSchema(); final int numV = 100; final long[] vids = new long[numV]; for (int i=0;i<numV;i++) { JanusGraphVertex v = graph.addVertex(prop,0); graph.tx().commit(); vids[i]=getId(v); } clopen(newConfig); resetEdgeCacheCounts(); final AtomicBoolean[] precommit = new AtomicBoolean[numV]; final AtomicBoolean[] postcommit = new AtomicBoolean[numV]; for (int i=0;i<numV;i++) { precommit[i]=new AtomicBoolean(false); postcommit[i]=new AtomicBoolean(false); } final AtomicInteger lookups = new AtomicInteger(0); final Random random = new Random(); final int updateSleepTime = 40; final int readSleepTime = 2; final int numReads = Math.round((numV*updateSleepTime)/readSleepTime*2.0f); Thread reader = new Thread(new Runnable() { @Override public void run() { int reads = 0; while (reads<numReads) { final int pos = random.nextInt(vids.length); long vid = vids[pos]; JanusGraphVertex v = getV(graph,vid); assertNotNull(v); boolean postCommit = postcommit[pos].get(); Integer value = v.value(prop); lookups.incrementAndGet(); assertNotNull("On pos [" + pos + "]", value); if (!precommit[pos].get()) assertEquals(0, value.intValue()); else if (postCommit) assertEquals(1, value.intValue()); graph.tx().commit(); try { Thread.sleep(readSleepTime); } catch (InterruptedException e) { return; } reads++; } } }); reader.start(); Thread updater = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<numV;i++) { try { JanusGraphVertex v = getV(graph,vids[i]); v.property(VertexProperty.Cardinality.single, prop, 1); precommit[i].set(true); graph.tx().commit(); postcommit[i].set(true); Thread.sleep(updateSleepTime); } catch (InterruptedException e) { throw new RuntimeException("Unexpected interruption",e); } } } }); updater.start(); updater.join(); // reader.start(); reader.join(); System.out.println("Retrievals: " + getEdgeCacheRetrievals()); System.out.println("Hits: " + (getEdgeCacheRetrievals()-getEdgeCacheMisses())); System.out.println("Misses: " + getEdgeCacheMisses()); assertEquals(numReads, lookups.get()); assertEquals(2 * numReads + 1 * numV, getEdgeCacheRetrievals()); int minMisses = 2*numV; assertTrue("Min misses ["+minMisses+"] vs actual ["+getEdgeCacheMisses()+"]",minMisses<=getEdgeCacheMisses() && 4*minMisses>=getEdgeCacheMisses()); } private long getEdgeCacheRetrievals() { return metric.getCounter(metricsPrefix, EDGESTORE_NAME + METRICS_CACHE_SUFFIX, CacheMetricsAction.RETRIEVAL.getName()).getCount(); } private long getEdgeCacheMisses() { return metric.getCounter(metricsPrefix, EDGESTORE_NAME + METRICS_CACHE_SUFFIX, CacheMetricsAction.MISS.getName()).getCount(); } private void resetEdgeCacheCounts() { Counter counter = metric.getCounter(metricsPrefix, EDGESTORE_NAME + METRICS_CACHE_SUFFIX, CacheMetricsAction.RETRIEVAL.getName()); counter.dec(counter.getCount()); counter = metric.getCounter(metricsPrefix, EDGESTORE_NAME + METRICS_CACHE_SUFFIX, CacheMetricsAction.MISS.getName()); counter.dec(counter.getCount()); } private void resetMetrics() { MetricManager.INSTANCE.getRegistry().removeMatching(MetricFilter.ALL); } /** * Tests cache performance */ @Test public void testCacheSpeedup() { Object[] newConfig = {option(GraphDatabaseConfiguration.DB_CACHE),true, option(GraphDatabaseConfiguration.DB_CACHE_TIME),0}; clopen(newConfig); int numV = 1000; JanusGraphVertex previous = null; for (int i=0;i<numV;i++) { JanusGraphVertex v = graph.addVertex("name", "v" + i); if (previous!=null) v.addEdge("knows",previous); previous = v; } graph.tx().commit(); long vertexId = getId(previous); assertCount(numV, graph.query().vertices()); clopen(newConfig); double timecoldglobal=0, timewarmglobal=0,timehotglobal=0; int outerRepeat = 20; int measurements = 10; assertTrue(measurements<outerRepeat); int innerRepeat = 2; for (int c=0;c<outerRepeat;c++) { double timecold = testAllVertices(vertexId,numV); double timewarm = 0; double timehot = 0; for (int i = 0;i<innerRepeat;i++) { graph.tx().commit(); timewarm += testAllVertices(vertexId,numV); for (int j=0;j<innerRepeat;j++) { timehot += testAllVertices(vertexId,numV); } } timewarm = timewarm / innerRepeat; timehot = timehot / (innerRepeat*innerRepeat); if (c>=(outerRepeat-measurements)) { timecoldglobal += timecold; timewarmglobal += timewarm; timehotglobal += timehot; } // System.out.println(timecold + "\t" + timewarm + "\t" + timehot); clopen(newConfig); } timecoldglobal = timecoldglobal/measurements; timewarmglobal = timewarmglobal/measurements; timehotglobal = timehotglobal/measurements; System.out.println(round(timecoldglobal) + "\t" + round(timewarmglobal) + "\t" + round(timehotglobal)); assertTrue(timecoldglobal + " vs " + timewarmglobal, timecoldglobal>timewarmglobal*2); //assertTrue(timewarmglobal + " vs " + timehotglobal, timewarmglobal>timehotglobal); Sometimes, this is not true } private double testAllVertices(long vid, int numV) { long start = System.nanoTime(); JanusGraphVertex v = getV(graph,vid); for (int i=1; i<numV; i++) { v = Iterables.<JanusGraphVertex>getOnlyElement(v.query().direction(Direction.OUT).labels("knows").vertices()); } return ((System.nanoTime()-start)/1000000.0); } }