private static void verifyMetrics(Metrics metric, boolean fromCache, boolean multiQuery) { assertTrue(metric.getDuration(TimeUnit.MICROSECONDS) > 0); assertTrue(metric.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > 0); String hasMultiQuery = (String) metric.getAnnotation(QueryProfiler.MULTIQUERY_ANNOTATION); assertTrue(multiQuery?hasMultiQuery.equalsIgnoreCase("true"):hasMultiQuery==null); for (Metrics submetric : metric.getNested()) { assertTrue(submetric.getDuration(TimeUnit.MICROSECONDS) > 0); switch (submetric.getName()) { case "optimization": assertNull(submetric.getCount(TraversalMetrics.ELEMENT_COUNT_ID)); break; case "backend-query": if (fromCache) assertFalse("Should not execute backend-queries when cached",true); assertTrue(submetric.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > 0); break; default: assertFalse("Unrecognized nested query: " + submetric.getName(),true); } } }
private static void verifyMetrics(Metrics metric, boolean fromCache, boolean multiQuery) { assertTrue(metric.getDuration(TimeUnit.MICROSECONDS) > 0); assertTrue(metric.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > 0); String hasMultiQuery = (String) metric.getAnnotation(QueryProfiler.MULTIQUERY_ANNOTATION); assertTrue(multiQuery ? hasMultiQuery.equalsIgnoreCase("true") : hasMultiQuery == null); for (Metrics subMetric : metric.getNested()) { assertTrue(subMetric.getDuration(TimeUnit.MICROSECONDS) > 0); switch (subMetric.getName()) { case "optimization": assertNull(subMetric.getCount(TraversalMetrics.ELEMENT_COUNT_ID)); break; case "backend-query": if (fromCache) assertFalse("Should not execute backend-queries when cached", true); assertTrue(subMetric.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > 0); break; default: assertFalse("Unrecognized nested query: " + subMetric.getName(), true); } } }
private void validate_g_V_sideEffectXThread_sleepX10XX_sideEffectXThread_sleepX5XX_profile(final TraversalMetrics traversalMetrics) { traversalMetrics.toString(); // ensure no exceptions are thrown assumeThat("The following assertions apply to TinkerGraph only as provider strategies can alter the steps to not comply with expectations", graph.getClass().getSimpleName(), equalTo("TinkerGraph")); // Grab the second (sideEffect{sleep}) step and check the times. Metrics metrics = traversalMetrics.getMetrics(1); // 6 elements w/ a 10ms sleep each = 60ms with 10ms for other computation. assertTrue("Duration should be at least the length of the sleep (59ms): " + metrics.getDuration(TimeUnit.MILLISECONDS), metrics.getDuration(TimeUnit.MILLISECONDS) >= 59); // 6 elements w/ a 5ms sleep each = 30ms plus 20ms for other computation metrics = traversalMetrics.getMetrics(2); assertTrue("Duration should be at least the length of the sleep (29ms): " + metrics.getDuration(TimeUnit.MILLISECONDS), metrics.getDuration(TimeUnit.MILLISECONDS) >= 29); double totalPercentDuration = 0; for (Metrics m : traversalMetrics.getMetrics()) { totalPercentDuration += (Double) m.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY); } assertEquals(100, totalPercentDuration, 0.000001); }
private static Map<String, Object> metricsToMap(final Metrics metrics) { final Map<String, Object> m = new HashMap<>(); m.put(GraphSONTokens.ID, metrics.getId()); m.put(GraphSONTokens.NAME, metrics.getName()); m.put(GraphSONTokens.COUNTS, metrics.getCounts()); m.put(GraphSONTokens.DURATION, metrics.getDuration(TimeUnit.NANOSECONDS) / 1000000d); if (!metrics.getAnnotations().isEmpty()) { m.put(GraphSONTokens.ANNOTATIONS, metrics.getAnnotations()); } if (!metrics.getNested().isEmpty()) { final List<Map<String, Object>> nested = new ArrayList<>(); metrics.getNested().forEach(it -> nested.add(metricsToMap(it))); m.put(GraphSONTokens.METRICS, nested); } return m; } }
/** * Create a {@code MutableMetrics} from an immutable one. */ public MutableMetrics(final Metrics other) { this.id = other.getId(); this.name = other.getName(); this.annotations.putAll(other.getAnnotations()); this.durationNs = other.getDuration(TimeUnit.NANOSECONDS); other.getCounts().forEach((key, count) -> this.counts.put(key, new AtomicLong(count))); other.getNested().forEach(nested -> this.addNested(new MutableMetrics(nested))); }
@Override public void serialize(final Metrics metrics, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException { final Map<String, Object> m = new HashMap<>(); m.put(GraphSONTokens.ID, metrics.getId()); m.put(GraphSONTokens.NAME, metrics.getName()); m.put(GraphSONTokens.COUNTS, metrics.getCounts()); m.put(GraphSONTokens.DURATION, metrics.getDuration(TimeUnit.NANOSECONDS) / 1000000d); if (!metrics.getAnnotations().isEmpty()) { m.put(GraphSONTokens.ANNOTATIONS, metrics.getAnnotations()); } if (!metrics.getNested().isEmpty()) { final List<Metrics> nested = new ArrayList<>(); metrics.getNested().forEach(it -> nested.add(it)); m.put(GraphSONTokens.METRICS, nested); } jsonGenerator.writeObject(m); } }
@Override public void serialize(final Metrics metrics, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException { final Map<String, Object> m = new HashMap<>(); m.put(GraphSONTokens.ID, metrics.getId()); m.put(GraphSONTokens.NAME, metrics.getName()); m.put(GraphSONTokens.COUNTS, metrics.getCounts()); m.put(GraphSONTokens.DURATION, metrics.getDuration(TimeUnit.NANOSECONDS) / 1000000d); if (!metrics.getAnnotations().isEmpty()) { m.put(GraphSONTokens.ANNOTATIONS, metrics.getAnnotations()); } if (!metrics.getNested().isEmpty()) { final List<Metrics> nested = new ArrayList<>(); metrics.getNested().forEach(it -> nested.add(it)); m.put(GraphSONTokens.METRICS, nested); } jsonGenerator.writeObject(m); } }
sb.append(String.format(" %15.3f", m.getDuration(TimeUnit.MICROSECONDS) / 1000.0));
@Override public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final Metrics object) { output.writeString(object.getId()); output.writeString(object.getName()); output.writeDouble(object.getDuration(TimeUnit.NANOSECONDS) / 1000000d); kryo.writeObject(output, object.getCounts()); // annotations is a synchronized LinkedHashMap - get rid of the "synch" for serialization as gryo // doesn't know how to deserialize that well and LinkedHashMap should work with 3.3.x and previous final Map<String, Object> annotations = new LinkedHashMap<>(); object.getAnnotations().forEach(annotations::put); kryo.writeObject(output, annotations); // kryo might have a problem with LinkedHashMap value collections. can't recreate it independently but // it gets fixed with standard collections for some reason. final List<Metrics> nested = new ArrayList<>(object.getNested()); kryo.writeObject(output, nested); }
private void validate_g_V_out_out_profile_grateful(final TraversalMetrics traversalMetrics) { traversalMetrics.toString(); // ensure no exceptions are thrown assumeThat("The following assertions apply to TinkerGraph only as provider strategies can alter the steps to not comply with expectations", graph.getClass().getSimpleName(), equalTo("TinkerGraph")); Metrics metrics = traversalMetrics.getMetrics(0); assertEquals(808, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue()); assertEquals(808, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue()); assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) >= 0); assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) >= 0); metrics = traversalMetrics.getMetrics(1); assertEquals(8049, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue()); assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue()); assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) >= 0); assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) >= 0); metrics = traversalMetrics.getMetrics(2); assertEquals(327370, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue()); assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue()); assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) >= 0); assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) >= 0); double totalPercentDuration = 0; for (Metrics m : traversalMetrics.getMetrics()) { totalPercentDuration += (Double) m.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY); } assertEquals(100, totalPercentDuration, 0.000001); }
private void validate_g_V_repeat_both_modern_profile(final TraversalMetrics traversalMetrics, final boolean withRepeatUnrollStrategy) { traversalMetrics.toString(); // ensure no exceptions are thrown assumeThat("The following assertions apply to TinkerGraph only as provider strategies can alter the steps to not comply with expectations", graph.getClass().getSimpleName(), equalTo("TinkerGraph")); Metrics metrics = traversalMetrics.getMetrics(0); assertEquals(6, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue()); assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue()); metrics = traversalMetrics.getMetrics(1); assertEquals(withRepeatUnrollStrategy ? 12 : 72, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue()); assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue()); if (!withRepeatUnrollStrategy) assertTrue("Count should be greater than traversers.", metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue()); assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) >= 0); assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) >= 0); // Test the nested global metrics of the repeat step if (!withRepeatUnrollStrategy) { final Metrics vertexStepNestedInRepeat = (Metrics) metrics.getNested().toArray()[0]; assertEquals(114, vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue()); assertNotEquals(0, vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue()); assertTrue("Count should be greater than traversers.", vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue()); assertTrue("Times should be positive.", vertexStepNestedInRepeat.getDuration(TimeUnit.MICROSECONDS) >= 0); } double totalPercentDuration = 0; for (Metrics m : traversalMetrics.getMetrics()) { totalPercentDuration += (Double) m.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY); } assertEquals(100, totalPercentDuration, 0.000001); }
@Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldSerializeTraversalMetrics() throws Exception { final ObjectMapper mapper = graph.io(GraphSONIo.build(GraphSONVersion.V2_0)).mapper().version(GraphSONVersion.V2_0).create().createMapper(); final TraversalMetrics before = g.V().both().profile().next(); final String json = mapper.writeValueAsString(before); final TraversalMetrics after = mapper.readValue(json, TraversalMetrics.class); assertNotNull(after); assertEquals(before.getMetrics().size(), after.getMetrics().size()); assertEquals(before.getDuration(TimeUnit.MILLISECONDS), after.getDuration(TimeUnit.MILLISECONDS)); assertEquals(before.getMetrics().size(), after.getMetrics().size()); before.getMetrics().forEach(b -> { final Optional<? extends Metrics> mFromA = after.getMetrics().stream().filter(a -> b.getId().equals(a.getId())).findFirst(); if (mFromA.isPresent()) { final Metrics m = mFromA.get(); assertEquals(b.getAnnotations(), m.getAnnotations()); assertEquals(b.getCounts(), m.getCounts()); assertEquals(b.getName(), m.getName()); assertEquals(b.getDuration(TimeUnit.MILLISECONDS), m.getDuration(TimeUnit.MILLISECONDS)); } else { fail("Metrics were not present after deserialization"); } }); }
@Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldSerializeTraversalMetrics() throws Exception { final ObjectMapper mapper = graph.io(GraphSONIo.build(GraphSONVersion.V3_0)).mapper().version(GraphSONVersion.V3_0).create().createMapper(); final TraversalMetrics before = g.V().both().profile().next(); final String json = mapper.writeValueAsString(before); final TraversalMetrics after = mapper.readValue(json, TraversalMetrics.class); assertNotNull(after); assertEquals(before.getMetrics().size(), after.getMetrics().size()); assertEquals(before.getDuration(TimeUnit.MILLISECONDS), after.getDuration(TimeUnit.MILLISECONDS)); assertEquals(before.getMetrics().size(), after.getMetrics().size()); before.getMetrics().forEach(b -> { final Optional<? extends Metrics> mFromA = after.getMetrics().stream().filter(a -> b.getId().equals(a.getId())).findFirst(); if (mFromA.isPresent()) { final Metrics m = mFromA.get(); assertEquals(b.getAnnotations(), m.getAnnotations()); assertEquals(b.getCounts(), m.getCounts()); assertEquals(b.getName(), m.getName()); assertEquals(b.getDuration(TimeUnit.MILLISECONDS), m.getDuration(TimeUnit.MILLISECONDS)); } else { fail("Metrics were not present after deserialization"); } }); }
@Override protected ByteBuf writeValue(final Metrics value, final ByteBufAllocator allocator, final GraphBinaryWriter context) throws SerializationException { return allocator.compositeBuffer(6).addComponents(true, context.writeValue(value.getId(), allocator, false), context.writeValue(value.getName(), allocator, false), context.writeValue(value.getDuration(TimeUnit.NANOSECONDS), allocator, false), context.writeValue(value.getCounts(), allocator, false), context.writeValue(value.getAnnotations(), allocator, false), // Avoid changing type to List collectionSerializer.writeValue(value.getNested(), allocator, context)); } }
private static Map<String, Object> metricsToMap(final Metrics metrics) { final Map<String, Object> m = new HashMap<>(); m.put(GraphSONTokens.ID, metrics.getId()); m.put(GraphSONTokens.NAME, metrics.getName()); m.put(GraphSONTokens.COUNTS, metrics.getCounts()); m.put(GraphSONTokens.DURATION, metrics.getDuration(TimeUnit.NANOSECONDS) / 1000000d); if (!metrics.getAnnotations().isEmpty()) { m.put(GraphSONTokens.ANNOTATIONS, metrics.getAnnotations()); } if (!metrics.getNested().isEmpty()) { final List<Map<String, Object>> nested = new ArrayList<>(); metrics.getNested().forEach(it -> nested.add(metricsToMap(it))); m.put(GraphSONTokens.METRICS, nested); } return m; } }
@Override public void serialize(final Metrics metrics, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException { final Map<String, Object> m = new HashMap<>(); m.put(GraphSONTokens.ID, metrics.getId()); m.put(GraphSONTokens.NAME, metrics.getName()); m.put(GraphSONTokens.COUNTS, metrics.getCounts()); m.put(GraphSONTokens.DURATION, metrics.getDuration(TimeUnit.NANOSECONDS) / 1000000d); if (!metrics.getAnnotations().isEmpty()) { m.put(GraphSONTokens.ANNOTATIONS, metrics.getAnnotations()); } if (!metrics.getNested().isEmpty()) { final List<Metrics> nested = new ArrayList<>(); metrics.getNested().forEach(it -> nested.add(it)); m.put(GraphSONTokens.METRICS, nested); } jsonGenerator.writeObject(m); } }
@Override public void serialize(final Metrics metrics, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException { final Map<String, Object> m = new HashMap<>(); m.put(GraphSONTokens.ID, metrics.getId()); m.put(GraphSONTokens.NAME, metrics.getName()); m.put(GraphSONTokens.COUNTS, metrics.getCounts()); m.put(GraphSONTokens.DURATION, metrics.getDuration(TimeUnit.NANOSECONDS) / 1000000d); if (!metrics.getAnnotations().isEmpty()) { m.put(GraphSONTokens.ANNOTATIONS, metrics.getAnnotations()); } if (!metrics.getNested().isEmpty()) { final List<Metrics> nested = new ArrayList<>(); metrics.getNested().forEach(it -> nested.add(it)); m.put(GraphSONTokens.METRICS, nested); } jsonGenerator.writeObject(m); } }
/** * Create a {@code MutableMetrics} from an immutable one. */ public MutableMetrics(final Metrics other) { this.id = other.getId(); this.name = other.getName(); this.annotations.putAll(other.getAnnotations()); this.durationNs = other.getDuration(TimeUnit.NANOSECONDS); other.getCounts().forEach((key, count) -> this.counts.put(key, new AtomicLong(count))); other.getNested().forEach(nested -> this.addNested(new MutableMetrics(nested))); }
@Override public <O extends OutputShim> void write(final KryoShim<?, O> kryo, final O output, final Metrics object) { output.writeString(object.getId()); output.writeString(object.getName()); output.writeDouble(object.getDuration(TimeUnit.NANOSECONDS) / 1000000d); kryo.writeObject(output, object.getCounts()); // annotations is a synchronized LinkedHashMap - get rid of the "synch" for serialization as gryo // doesn't know how to deserialize that well and LinkedHashMap should work with 3.3.x and previous final Map<String, Object> annotations = new LinkedHashMap<>(); object.getAnnotations().forEach(annotations::put); kryo.writeObject(output, annotations); // kryo might have a problem with LinkedHashMap value collections. can't recreate it independently but // it gets fixed with standard collections for some reason. final List<Metrics> nested = new ArrayList<>(object.getNested()); kryo.writeObject(output, nested); }
@Override public ByteBuf writeValue(final Metrics value, final ByteBufAllocator allocator, final GraphBinaryWriter context) throws SerializationException { return allocator.compositeBuffer(6).addComponents(true, context.writeValue(value.getId(), allocator, false), context.writeValue(value.getName(), allocator, false), context.writeValue(value.getDuration(TimeUnit.NANOSECONDS), allocator, false), context.writeValue(value.getCounts(), allocator, false), context.writeValue(value.getAnnotations(), allocator, false), // Avoid changing type to List collectionSerializer.writeValue(value.getNested(), allocator, context)); } }