Skip to content

Commit

Permalink
Introduce KernelStatisticProvider to separate cypher from new store d…
Browse files Browse the repository at this point in the history
…ependencies.

And ProfileKernelStatisticProvider as it de facto implementation that will
provide execution statistic.
  • Loading branch information
MishaDemianenko committed Mar 15, 2017
1 parent b245427 commit 6fde983
Show file tree
Hide file tree
Showing 15 changed files with 122 additions and 45 deletions.
Expand Up @@ -26,7 +26,6 @@ import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions.{Expander, K
import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.PatternNode import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.PatternNode
import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection
import org.neo4j.graphdb.{Node, Path, PropertyContainer, Relationship} import org.neo4j.graphdb.{Node, Path, PropertyContainer, Relationship}
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer


import scala.collection.Iterator import scala.collection.Iterator


Expand Down Expand Up @@ -212,7 +211,7 @@ class DelegatingQueryContext(val inner: QueryContext) extends QueryContext {


override def assertSchemaWritesAllowed(): Unit = inner.assertSchemaWritesAllowed() override def assertSchemaWritesAllowed(): Unit = inner.assertSchemaWritesAllowed()


override def pageCursorTracer(): PageCursorTracer = inner.pageCursorTracer() override def kernelStatisticProvider(): KernelStatisticProvider = inner.kernelStatisticProvider()
} }


class DelegatingOperations[T <: PropertyContainer](protected val inner: Operations[T]) extends Operations[T] { class DelegatingOperations[T <: PropertyContainer](protected val inner: Operations[T]) extends Operations[T] {
Expand Down
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2002-2017 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.cypher.internal.compiler.v3_2.spi

/**
* Expose various query execution kernel statistics
*/
trait KernelStatisticProvider {
/**
* @return observed page cache hits that was caused by particular query execution
*/
def getPageCacheHits: Long

/**
* @return observer page cache misses that was caused by particular query execution
*/
def getPageCacheMisses: Long
}

object EmptyKernelStatisticProvider extends KernelStatisticProvider {
override def getPageCacheHits: Long = 0

override def getPageCacheMisses: Long = 0
}
Expand Up @@ -26,7 +26,6 @@ import org.neo4j.cypher.internal.compiler.v3_2.pipes.matching.PatternNode
import org.neo4j.cypher.internal.compiler.v3_2.{IndexDescriptor, InternalQueryStatistics} import org.neo4j.cypher.internal.compiler.v3_2.{IndexDescriptor, InternalQueryStatistics}
import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection
import org.neo4j.graphdb.{Node, Path, PropertyContainer, Relationship} import org.neo4j.graphdb.{Node, Path, PropertyContainer, Relationship}
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer


import scala.collection.Iterator import scala.collection.Iterator


Expand Down Expand Up @@ -180,7 +179,7 @@ trait QueryContext extends TokenContext {


def assertSchemaWritesAllowed(): Unit def assertSchemaWritesAllowed(): Unit


def pageCursorTracer() : PageCursorTracer def kernelStatisticProvider() : KernelStatisticProvider
} }


trait Operations[T <: PropertyContainer] { trait Operations[T <: PropertyContainer] {
Expand Down
Expand Up @@ -25,12 +25,11 @@ import org.mockito.Mockito._
import org.neo4j.cypher.internal.compiler.v3_2.commands._ import org.neo4j.cypher.internal.compiler.v3_2.commands._
import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions.Literal import org.neo4j.cypher.internal.compiler.v3_2.commands.expressions.Literal
import org.neo4j.cypher.internal.compiler.v3_2.pipes.QueryStateHelper import org.neo4j.cypher.internal.compiler.v3_2.pipes.QueryStateHelper
import org.neo4j.cypher.internal.compiler.v3_2.spi.{PlanContext, QueryContext, QueryContextAdaptation} import org.neo4j.cypher.internal.compiler.v3_2.spi._
import org.neo4j.cypher.internal.compiler.v3_2.{ExecutionContext, IndexDescriptor} import org.neo4j.cypher.internal.compiler.v3_2.{ExecutionContext, IndexDescriptor}
import org.neo4j.cypher.internal.frontend.v3_2.IndexHintException import org.neo4j.cypher.internal.frontend.v3_2.IndexHintException
import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite
import org.neo4j.graphdb.Node import org.neo4j.graphdb.Node
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer


class EntityProducerFactoryTest extends CypherFunSuite { class EntityProducerFactoryTest extends CypherFunSuite {
var planContext: PlanContext = null var planContext: PlanContext = null
Expand Down Expand Up @@ -87,8 +86,8 @@ class EntityProducerFactoryTest extends CypherFunSuite {
Iterator.empty Iterator.empty
} }


override def pageCursorTracer(): PageCursorTracer = { override def kernelStatisticProvider(): KernelStatisticProvider = {
PageCursorTracer.NULL EmptyKernelStatisticProvider
} }
} }
val state = QueryStateHelper.emptyWith(query = queryContext) val state = QueryStateHelper.emptyWith(query = queryContext)
Expand Down
Expand Up @@ -26,7 +26,6 @@ import org.neo4j.cypher.internal.compiler.v3_2.spi._
import org.neo4j.cypher.internal.frontend.v3_2.ast.AstConstructionTestSupport import org.neo4j.cypher.internal.frontend.v3_2.ast.AstConstructionTestSupport
import org.neo4j.cypher.internal.frontend.v3_2.symbols._ import org.neo4j.cypher.internal.frontend.v3_2.symbols._
import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer


class ProcedureCallPipeTest class ProcedureCallPipeTest
extends CypherFunSuite extends CypherFunSuite
Expand Down Expand Up @@ -131,8 +130,8 @@ class ProcedureCallPipeTest
result(args) result(args)
} }


override def pageCursorTracer(): PageCursorTracer = { override def kernelStatisticProvider(): KernelStatisticProvider = {
PageCursorTracer.NULL EmptyKernelStatisticProvider
} }
} }
} }
Expand Up @@ -28,7 +28,6 @@ import org.neo4j.cypher.internal.compiler.v3_2.spi.{QualifiedName, _}
import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection import org.neo4j.cypher.internal.frontend.v3_2.SemanticDirection
import org.neo4j.cypher.internal.spi.v3_2.ExceptionTranslationSupport import org.neo4j.cypher.internal.spi.v3_2.ExceptionTranslationSupport
import org.neo4j.graphdb.{Node, Path, PropertyContainer, Relationship} import org.neo4j.graphdb.{Node, Path, PropertyContainer, Relationship}
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer


import scala.collection.Iterator import scala.collection.Iterator


Expand Down Expand Up @@ -236,7 +235,7 @@ class ExceptionTranslatingQueryContext(val inner: QueryContext) extends QueryCon


override def assertSchemaWritesAllowed(): Unit = translateException(inner.assertSchemaWritesAllowed()) override def assertSchemaWritesAllowed(): Unit = translateException(inner.assertSchemaWritesAllowed())


override def pageCursorTracer(): PageCursorTracer = translateException(inner.pageCursorTracer()) override def kernelStatisticProvider(): KernelStatisticProvider = translateException(inner.kernelStatisticProvider())


class ExceptionTranslatingOperations[T <: PropertyContainer](inner: Operations[T]) class ExceptionTranslatingOperations[T <: PropertyContainer](inner: Operations[T])
extends DelegatingOperations[T](inner) { extends DelegatingOperations[T](inner) {
Expand Down
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2002-2017 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.cypher.internal.compatibility.v3_2

import org.neo4j.cypher.internal.compiler.v3_2.spi.KernelStatisticProvider
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer

class ProfileKernelStatisticProvider(pageCursorTracer: PageCursorTracer) extends KernelStatisticProvider {

override def getPageCacheHits: Long = {
pageCursorTracer.hits()
}

override def getPageCacheMisses: Long = {
pageCursorTracer.faults()
}
}
Expand Up @@ -25,6 +25,7 @@ import java.util.function.Predicate
import org.neo4j.collection.RawIterator import org.neo4j.collection.RawIterator
import org.neo4j.collection.primitive.PrimitiveLongIterator import org.neo4j.collection.primitive.PrimitiveLongIterator
import org.neo4j.collection.primitive.base.Empty.EMPTY_PRIMITIVE_LONG_COLLECTION import org.neo4j.collection.primitive.base.Empty.EMPTY_PRIMITIVE_LONG_COLLECTION
import org.neo4j.cypher.internal.compatibility.v3_2.ProfileKernelStatisticProvider
import org.neo4j.cypher.internal.compiler.v3_2.MinMaxOrdering.{BY_NUMBER, BY_STRING, BY_VALUE} import org.neo4j.cypher.internal.compiler.v3_2.MinMaxOrdering.{BY_NUMBER, BY_STRING, BY_VALUE}
import org.neo4j.cypher.internal.compiler.v3_2._ import org.neo4j.cypher.internal.compiler.v3_2._
import org.neo4j.cypher.internal.compiler.v3_2.ast.convert.commands.DirectionConverter.toGraphDb import org.neo4j.cypher.internal.compiler.v3_2.ast.convert.commands.DirectionConverter.toGraphDb
Expand All @@ -45,7 +46,6 @@ import org.neo4j.graphdb.RelationshipType._
import org.neo4j.graphdb._ import org.neo4j.graphdb._
import org.neo4j.graphdb.security.URLAccessValidationError import org.neo4j.graphdb.security.URLAccessValidationError
import org.neo4j.graphdb.traversal.{Evaluators, TraversalDescription, Uniqueness} import org.neo4j.graphdb.traversal.{Evaluators, TraversalDescription, Uniqueness}
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer
import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.GraphDatabaseQueryService
import org.neo4j.kernel.api._ import org.neo4j.kernel.api._
import org.neo4j.kernel.api.exceptions.ProcedureException import org.neo4j.kernel.api.exceptions.ProcedureException
Expand Down Expand Up @@ -740,8 +740,8 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional
override def assertSchemaWritesAllowed(): Unit = override def assertSchemaWritesAllowed(): Unit =
transactionalContext.statement.schemaWriteOperations() transactionalContext.statement.schemaWriteOperations()


override def pageCursorTracer(): PageCursorTracer = { override def kernelStatisticProvider(): KernelStatisticProvider = {
transactionalContext.statement.asInstanceOf[KernelStatement].getPageCursorTracer new ProfileKernelStatisticProvider(transactionalContext.statement.asInstanceOf[KernelStatement].getPageCursorTracer)
} }
} }


Expand Down
Expand Up @@ -177,14 +177,12 @@ class TransactionBoundQueryContextTest extends CypherFunSuite {
val transactionalContext = TransactionalContextWrapper(createTransactionContext(graph, tx)) val transactionalContext = TransactionalContextWrapper(createTransactionContext(graph, tx))
val context = new TransactionBoundQueryContext(transactionalContext)(indexSearchMonitor) val context = new TransactionBoundQueryContext(transactionalContext)(indexSearchMonitor)


val tracer = context.pageCursorTracer() val tracer = context.kernelStatisticProvider()
tracer.hits() should equal(0) tracer.getPageCacheHits should equal(0)
tracer.pins() should equal(0)


graph.getNodeById(2) graph.getNodeById(2)
graph.getNodeById(1) graph.getNodeById(1)
tracer.hits() should equal(2) tracer.getPageCacheHits should equal(2)
tracer.pins() should equal(2)


tx.close() tx.close()
} }
Expand Down
8 changes: 7 additions & 1 deletion enterprise/cypher/cypher-compiled-runtime-3.2/pom.xml
Expand Up @@ -162,7 +162,13 @@
<version>${project.version}</version> <version>${project.version}</version>
<type>test-jar</type> <type>test-jar</type>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-cypher</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>


<!-- other --> <!-- other -->


Expand Down
Expand Up @@ -25,7 +25,7 @@
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.QueryExecutionEvent; import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.QueryExecutionEvent;
import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.QueryExecutionTracer; import org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.QueryExecutionTracer;
import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id; import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id;
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer; import org.neo4j.cypher.internal.compiler.v3_2.spi.KernelStatisticProvider;


public class ProfilingTracer implements QueryExecutionTracer public class ProfilingTracer implements QueryExecutionTracer
{ {
Expand All @@ -48,18 +48,18 @@ public interface Clock
private static final Data ZERO = new Data(); private static final Data ZERO = new Data();


private final Clock clock; private final Clock clock;
private final PageCursorTracer pageCursorTracer; private final KernelStatisticProvider statisticProvider;
private final Map<Id, Data> data = new HashMap<>(); private final Map<Id, Data> data = new HashMap<>();


public ProfilingTracer( PageCursorTracer pageCursorTracer ) public ProfilingTracer( KernelStatisticProvider statisticProvider )
{ {
this( Clock.SYSTEM_TIMER, pageCursorTracer ); this( Clock.SYSTEM_TIMER, statisticProvider );
} }


ProfilingTracer( Clock clock, PageCursorTracer pageCursorTracer ) ProfilingTracer( Clock clock, KernelStatisticProvider statisticProvider )
{ {
this.clock = clock; this.clock = clock;
this.pageCursorTracer = pageCursorTracer; this.statisticProvider = statisticProvider;
} }


public ProfilingInformation get( Id query ) public ProfilingInformation get( Id query )
Expand Down Expand Up @@ -91,22 +91,22 @@ public QueryExecutionEvent executeOperator( Id queryId )
{ {
this.data.put( queryId, data = new Data() ); this.data.put( queryId, data = new Data() );
} }
return new ExecutionEvent( clock, pageCursorTracer, data ); return new ExecutionEvent( clock, statisticProvider, data );
} }


private static class ExecutionEvent implements QueryExecutionEvent private static class ExecutionEvent implements QueryExecutionEvent
{ {
private final long start; private final long start;
private final Clock clock; private final Clock clock;
private final PageCursorTracer pageCursorTracer; private final KernelStatisticProvider statisticProvider;
private final Data data; private final Data data;
private long hitCount; private long hitCount;
private long rowCount; private long rowCount;


ExecutionEvent( Clock clock, PageCursorTracer pageCursorTracer, Data data ) ExecutionEvent( Clock clock, KernelStatisticProvider statisticProvider, Data data )
{ {
this.clock = clock; this.clock = clock;
this.pageCursorTracer = pageCursorTracer; this.statisticProvider = statisticProvider;
this.data = data; this.data = data;
this.start = clock.nanoTime(); this.start = clock.nanoTime();
} }
Expand All @@ -115,8 +115,8 @@ private static class ExecutionEvent implements QueryExecutionEvent
public void close() public void close()
{ {
long executionTime = clock.nanoTime() - start; long executionTime = clock.nanoTime() - start;
long pageCacheHits = pageCursorTracer.hits(); long pageCacheHits = statisticProvider.getPageCacheHits();
long pageCacheFaults = pageCursorTracer.faults(); long pageCacheFaults = statisticProvider.getPageCacheMisses();
if ( data != null ) if ( data != null )
{ {
data.update( executionTime, hitCount, rowCount, pageCacheHits, pageCacheFaults ); data.update( executionTime, hitCount, rowCount, pageCacheHits, pageCacheFaults );
Expand Down
Expand Up @@ -94,7 +94,7 @@ object BuildCompiledExecutionPlan extends Phase[CompiledRuntimeContext, Compilat


private def createTracer(mode: ExecutionMode, queryContext: QueryContext): DescriptionProvider = mode match { private def createTracer(mode: ExecutionMode, queryContext: QueryContext): DescriptionProvider = mode match {
case ProfileMode => case ProfileMode =>
val tracer = new ProfilingTracer(queryContext.pageCursorTracer()) val tracer = new ProfilingTracer(queryContext.kernelStatisticProvider())
(description: InternalPlanDescription) => (description: InternalPlanDescription) =>
(new Provider[InternalPlanDescription] { (new Provider[InternalPlanDescription] {


Expand Down
Expand Up @@ -35,7 +35,7 @@ object ExecutionPlanBuilder {


def tracer(mode: ExecutionMode, queryContext: QueryContext): DescriptionProvider = mode match { def tracer(mode: ExecutionMode, queryContext: QueryContext): DescriptionProvider = mode match {
case ProfileMode => case ProfileMode =>
val tracer = new ProfilingTracer(queryContext.pageCursorTracer()) val tracer = new ProfilingTracer(queryContext.kernelStatisticProvider())
(description: InternalPlanDescription) => (description: InternalPlanDescription) =>
(new Provider[InternalPlanDescription] { (new Provider[InternalPlanDescription] {


Expand Down
Expand Up @@ -19,9 +19,11 @@
*/ */
package org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.profiling package org.neo4j.cypher.internal.compiled_runtime.v3_2.codegen.profiling


import org.neo4j.cypher.internal.compatibility.v3_2.ProfileKernelStatisticProvider
import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id import org.neo4j.cypher.internal.compiler.v3_2.planDescription.Id
import org.neo4j.cypher.internal.compiler.v3_2.spi.EmptyKernelStatisticProvider
import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite import org.neo4j.cypher.internal.frontend.v3_2.test_helpers.CypherFunSuite
import org.neo4j.io.pagecache.tracing.cursor.{DefaultPageCursorTracer, PageCursorTracer} import org.neo4j.io.pagecache.tracing.cursor.DefaultPageCursorTracer


class ProfilingTracerTest extends CypherFunSuite { class ProfilingTracerTest extends CypherFunSuite {


Expand All @@ -38,7 +40,7 @@ class ProfilingTracerTest extends CypherFunSuite {
// given // given
val clock = new Clock val clock = new Clock
val operatorId = new Id val operatorId = new Id
val tracer = new ProfilingTracer(clock, PageCursorTracer.NULL) val tracer = new ProfilingTracer(clock, EmptyKernelStatisticProvider)
val event = tracer.executeOperator(operatorId) val event = tracer.executeOperator(operatorId)


// when // when
Expand All @@ -53,7 +55,7 @@ class ProfilingTracerTest extends CypherFunSuite {
// given // given
val clock = new Clock val clock = new Clock
val operatorId = new Id val operatorId = new Id
val tracer = new ProfilingTracer(clock, PageCursorTracer.NULL) val tracer = new ProfilingTracer(clock, EmptyKernelStatisticProvider)


// when // when
val event1 = tracer.executeOperator(operatorId) val event1 = tracer.executeOperator(operatorId)
Expand All @@ -71,7 +73,7 @@ class ProfilingTracerTest extends CypherFunSuite {
test("shouldReportDbHitsOfQueryExecution") { test("shouldReportDbHitsOfQueryExecution") {
// given // given
val operatorId = new Id val operatorId = new Id
val tracer = new ProfilingTracer(PageCursorTracer.NULL) val tracer = new ProfilingTracer(EmptyKernelStatisticProvider)
val event = tracer.executeOperator(operatorId) val event = tracer.executeOperator(operatorId)


// when // when
Expand All @@ -88,7 +90,7 @@ class ProfilingTracerTest extends CypherFunSuite {
test("shouldReportRowsOfQueryExecution") { test("shouldReportRowsOfQueryExecution") {
// given // given
val operatorId = new Id val operatorId = new Id
val tracer = new ProfilingTracer(PageCursorTracer.NULL) val tracer = new ProfilingTracer(EmptyKernelStatisticProvider)
val event = tracer.executeOperator(operatorId) val event = tracer.executeOperator(operatorId)


// when // when
Expand All @@ -106,7 +108,7 @@ class ProfilingTracerTest extends CypherFunSuite {
test("report page cache hits as part of profiling statistics") { test("report page cache hits as part of profiling statistics") {
val operatorId = new Id val operatorId = new Id
val cursorTracer = new DefaultPageCursorTracer val cursorTracer = new DefaultPageCursorTracer
var tracer = new ProfilingTracer(cursorTracer) var tracer = new ProfilingTracer(new ProfileKernelStatisticProvider(cursorTracer))
val event = tracer.executeOperator(operatorId) val event = tracer.executeOperator(operatorId)


1 to 100 foreach { _ => { 1 to 100 foreach { _ => {
Expand All @@ -125,7 +127,7 @@ class ProfilingTracerTest extends CypherFunSuite {
test("report page cache misses as part of profiling statistics") { test("report page cache misses as part of profiling statistics") {
val operatorId = new Id val operatorId = new Id
val cursorTracer = new DefaultPageCursorTracer val cursorTracer = new DefaultPageCursorTracer
var tracer = new ProfilingTracer(cursorTracer) var tracer = new ProfilingTracer(new ProfileKernelStatisticProvider(cursorTracer))
val event = tracer.executeOperator(operatorId) val event = tracer.executeOperator(operatorId)


1 to 17 foreach { _ => { 1 to 17 foreach { _ => {
Expand Down

0 comments on commit 6fde983

Please sign in to comment.