Skip to content

Commit

Permalink
Added global page cache hit ratio to metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
klaren committed Jun 15, 2017
1 parent 649cea5 commit e0c883b
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 9 deletions.
Expand Up @@ -20,11 +20,36 @@
package org.neo4j.helpers; package org.neo4j.helpers;


import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Arrays;


public abstract class MathUtil public class MathUtil
{ {
private static final long NON_DOUBLE_LONG = 0xFFE0_0000_0000_0000L; // doubles are exact integers up to 53 bits private static final long NON_DOUBLE_LONG = 0xFFE0_0000_0000_0000L; // doubles are exact integers up to 53 bits


private MathUtil()
{
throw new AssertionError();
}

/**
* Calculates the portion of the first value to all values passed
*
* @param n The values in the set
* @return the ratio of n[0] to the sum all n, 0 if result is {@link Double#NaN}
*/
public static double portion( double... n )
{
assert n.length > 0;

double first = n[0];
if ( numbersEqual( first, 0 ) )
{
return 0d;
}
double total = Arrays.stream( n ).sum();
return first / total;
}

public static boolean numbersEqual( double fpn, long in ) public static boolean numbersEqual( double fpn, long in )
{ {
if ( in < 0 ) if ( in < 0 )
Expand Down
Expand Up @@ -19,6 +19,8 @@
*/ */
package org.neo4j.io.pagecache.monitoring; package org.neo4j.io.pagecache.monitoring;


import org.neo4j.helpers.MathUtil;

/** /**
* The PageCacheCounters exposes internal counters from the page cache. * The PageCacheCounters exposes internal counters from the page cache.
* The data for these counters is sourced through the PageCacheTracer API. * The data for these counters is sourced through the PageCacheTracer API.
Expand Down Expand Up @@ -50,6 +52,14 @@ public interface PageCacheCounters
*/ */
long hits(); long hits();


/**
* @return The cache hit ratio observed thus far.
*/
default double hitRatio()
{
return MathUtil.portion( hits(), faults() );
}

/** /**
* @return The number of page flushes observed thus far. * @return The number of page flushes observed thus far.
*/ */
Expand Down
Expand Up @@ -31,6 +31,7 @@


import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Locale;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;


Expand Down Expand Up @@ -75,6 +76,7 @@ public void init()
.convertRatesTo( TimeUnit.SECONDS ) .convertRatesTo( TimeUnit.SECONDS )
.convertDurationsTo( TimeUnit.MILLISECONDS ) .convertDurationsTo( TimeUnit.MILLISECONDS )
.filter( MetricFilter.ALL ) .filter( MetricFilter.ALL )
.formatFor( Locale.US )
.build( ensureDirectoryExists( outputPath ) ); .build( ensureDirectoryExists( outputPath ) );
} }


Expand Down
Expand Up @@ -47,6 +47,8 @@ public class PageCacheMetrics extends LifecycleAdapter
public static final String PC_PAGE_FAULTS = name( PAGE_CACHE_PREFIX, "page_faults" ); public static final String PC_PAGE_FAULTS = name( PAGE_CACHE_PREFIX, "page_faults" );
@Documented( "The total number of page hits happened in the page cache" ) @Documented( "The total number of page hits happened in the page cache" )
public static final String PC_HITS = name( PAGE_CACHE_PREFIX, "hits" ); public static final String PC_HITS = name( PAGE_CACHE_PREFIX, "hits" );
@Documented( "The ratio of hits to the total number of lookups in the page cache" )
public static final String PC_HIT_RATIO = name( PAGE_CACHE_PREFIX, "hit_ratio" );


private final MetricRegistry registry; private final MetricRegistry registry;
private final PageCacheCounters pageCacheCounters; private final PageCacheCounters pageCacheCounters;
Expand All @@ -67,6 +69,7 @@ public void start()
registry.register( PC_HITS, (Gauge<Long>) pageCacheCounters::hits ); registry.register( PC_HITS, (Gauge<Long>) pageCacheCounters::hits );
registry.register( PC_FLUSHES, (Gauge<Long>) pageCacheCounters::flushes ); registry.register( PC_FLUSHES, (Gauge<Long>) pageCacheCounters::flushes );
registry.register( PC_EVICTION_EXCEPTIONS, (Gauge<Long>) pageCacheCounters::evictionExceptions ); registry.register( PC_EVICTION_EXCEPTIONS, (Gauge<Long>) pageCacheCounters::evictionExceptions );
registry.register( PC_HIT_RATIO, (Gauge<Double>) pageCacheCounters::hitRatio );
} }


@Override @Override
Expand All @@ -79,5 +82,6 @@ public void stop()
registry.remove( PC_HITS ); registry.remove( PC_HITS );
registry.remove( PC_FLUSHES ); registry.remove( PC_FLUSHES );
registry.remove( PC_EVICTION_EXCEPTIONS ); registry.remove( PC_EVICTION_EXCEPTIONS );
registry.remove( PC_HIT_RATIO );
} }
} }
Expand Up @@ -24,6 +24,7 @@
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Function;


import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
Expand All @@ -33,34 +34,51 @@


public class MetricsTestHelper public class MetricsTestHelper
{ {
public static final int TIME_STAMP = 0; private static final int TIME_STAMP = 0;
public static final int METRICS_VALUE = 1; private static final int METRICS_VALUE = 1;


public static long readLongValue( File metricFile ) throws IOException, InterruptedException public static long readLongValue( File metricFile ) throws IOException, InterruptedException
{ {
return readLongValueAndAssert( metricFile, (one, two) -> true ); return readLongValueAndAssert( metricFile, ( one, two ) -> true );
} }


public static long readLongValueAndAssert( File metricFile, BiPredicate<Integer,Integer> assumption ) static long readLongValueAndAssert( File metricFile, BiPredicate<Long,Long> assumption )
throws IOException, InterruptedException throws IOException, InterruptedException
{
return readValueAndAssert( metricFile, 0L, Long::parseLong, assumption );
}

static double readDoubleValue( File metricFile ) throws IOException, InterruptedException
{
return readValueAndAssert( metricFile, 0.0, Double::parseDouble,
( one, two ) -> true );
}

private static <T> T readValueAndAssert( File metricFile, T startValue, Function<String,T> parser,
BiPredicate<T,T> assumption ) throws IOException, InterruptedException
{ {
// let's wait until the file is in place (since the reporting is async that might take a while) // let's wait until the file is in place (since the reporting is async that might take a while)
assertEventually( "Metrics file should exist", metricFile::exists, is( true ), 40, SECONDS ); assertEventually( "Metrics file should exist", metricFile::exists, is( true ), 40, SECONDS );


try ( BufferedReader reader = new BufferedReader( new FileReader( metricFile ) ) ) try ( BufferedReader reader = new BufferedReader( new FileReader( metricFile ) ) )
{ {
String[] headers = reader.readLine().split( "," ); String s;
do
{
s = reader.readLine();
}
while ( s == null );
String[] headers = s.split( "," );
assertThat( headers.length, is( 2 ) ); assertThat( headers.length, is( 2 ) );
assertThat( headers[TIME_STAMP], is( "t" ) ); assertThat( headers[TIME_STAMP], is( "t" ) );
assertThat( headers[METRICS_VALUE], is( "value" ) ); assertThat( headers[METRICS_VALUE], is( "value" ) );


// Now we can verify that the number of committed transactions should never decrease. T currentValue = startValue;
int currentValue = 0;
String line; String line;
while ( (line = reader.readLine()) != null ) while ( (line = reader.readLine()) != null )
{ {
String[] fields = line.split( "," ); String[] fields = line.split( "," );
int newValue = Integer.parseInt( fields[1] ); T newValue = parser.apply( fields[1] );
assertTrue( "assertion failed on " + newValue + " " + currentValue, assertTrue( "assertion failed on " + newValue + " " + currentValue,
assumption.test( newValue, currentValue ) ); assumption.test( newValue, currentValue ) );
currentValue = newValue; currentValue = newValue;
Expand Down
Expand Up @@ -43,7 +43,9 @@
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.neo4j.metrics.MetricsTestHelper.metricsCsv; import static org.neo4j.metrics.MetricsTestHelper.metricsCsv;
import static org.neo4j.metrics.MetricsTestHelper.readDoubleValue;
import static org.neo4j.metrics.MetricsTestHelper.readLongValue; import static org.neo4j.metrics.MetricsTestHelper.readLongValue;
import static org.neo4j.test.assertion.Assert.assertEventually; import static org.neo4j.test.assertion.Assert.assertEventually;


Expand Down Expand Up @@ -94,6 +96,12 @@ public void pageCacheMetrics() throws Exception
assertMetrics( "Page cache hits should be included in metrics report.", PageCacheMetrics.PC_HITS, greaterThan( 0L ) ); assertMetrics( "Page cache hits should be included in metrics report.", PageCacheMetrics.PC_HITS, greaterThan( 0L ) );
assertMetrics( "Page cache flushes should be included in metrics report.", PageCacheMetrics.PC_FLUSHES, greaterThanOrEqualTo( 0L ) ); assertMetrics( "Page cache flushes should be included in metrics report.", PageCacheMetrics.PC_FLUSHES, greaterThanOrEqualTo( 0L ) );
assertMetrics( "Page cache exceptions should be included in metrics report.", PageCacheMetrics.PC_EVICTION_EXCEPTIONS, equalTo( 0L ) ); assertMetrics( "Page cache exceptions should be included in metrics report.", PageCacheMetrics.PC_EVICTION_EXCEPTIONS, equalTo( 0L ) );

assertEventually(
"Page cache hit ratio should be included in metrics report.",
() -> readDoubleValue( metricsCsv( metricsDirectory, PageCacheMetrics.PC_HIT_RATIO ) ),
lessThanOrEqualTo( 1.0 ),
5, SECONDS );
} }


private void assertMetrics( String message, String metricName, Matcher<Long> matcher ) throws Exception private void assertMetrics( String message, String metricName, Matcher<Long> matcher ) throws Exception
Expand Down

0 comments on commit e0c883b

Please sign in to comment.