Documentation
¶
Overview ¶
Package explain renders Cypher execution plans as human-readable text (EXPLAIN mode) and instruments them with per-operator execution statistics (PROFILE mode).
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FormatReport ¶
func FormatReport(r ProfileReport) string
FormatReport formats r as a Neo4j-style table:
+--------------------------+--------+---------+-----------+ | Operator | Rows | DbHits | Time (ms) | +--------------------------+--------+---------+-----------+ | NodeByLabelScan | 100 | 100 | 0.012 | | ProduceResults | 100 | 0 | 0.001 | +--------------------------+--------+---------+-----------+ | Total | 200 | 100 | 0.013 | +--------------------------+--------+---------+-----------+
func TextTree ¶
func TextTree(plan ir.LogicalPlan) string
TextTree renders a physical plan in Neo4j-style columnar text:
+-------------------------+----------+----------+ | Operator | Est.Rows | Vars | +-------------------------+----------+----------+ | ProduceResults | 100 | n | | └─ NodeByLabelScan | 100 | n:Person | +-------------------------+----------+----------+
The Operator column is padded to the widest (name + tree-indent). Est.Rows comes from the [estimator] interface; nodes that do not implement it show "-". Vars lists the variables returned by ir.LogicalPlan.Vars.
Output is stable across runs: no map iteration order is relied upon. Children appear in ir.LogicalPlan.Children order.
Example ¶
ExampleTextTree renders a logical plan as a columnar text table. The tree follows the plan's child order, so the output is stable across runs.
package main
import (
"fmt"
"strings"
"github.com/FlavioCFOliveira/GoGraph/cypher/explain"
"github.com/FlavioCFOliveira/GoGraph/cypher/ir"
)
func main() {
plan := ir.NewProduceResults(
[]string{"n"},
ir.NewNodeByLabelScan("n", "Person"),
)
out := explain.TextTree(plan)
// The rendered table is a fixed-width box; assert its structure rather
// than embedding the exact padding so the example stays readable.
fmt.Println("has header:", strings.Contains(out, "Operator") && strings.Contains(out, "Est.Rows"))
fmt.Println("has root:", strings.Contains(out, "ProduceResults"))
fmt.Println("has child:", strings.Contains(out, "NodeByLabelScan"))
fmt.Println("child is nested:", strings.Contains(out, "└─ NodeByLabelScan"))
}
Output: has header: true has root: true has child: true child is nested: true
Types ¶
type DbHitsCounter ¶
type DbHitsCounter struct {
// contains filtered or unexported fields
}
DbHitsCounter is a per-pipeline counter for logical storage accesses (index lookups, property reads, CSR neighbour scans). It is incremented by instrumented operator wrappers and read by the PROFILE reporter.
DbHitsCounter is safe for concurrent use.
func (*DbHitsCounter) Add ¶
func (c *DbHitsCounter) Add(delta uint64)
Add increments the counter by delta.
func (*DbHitsCounter) Load ¶
func (c *DbHitsCounter) Load() uint64
Load returns the current counter value.
type InstrumentedScan ¶
type InstrumentedScan struct {
// contains filtered or unexported fields
}
InstrumentedScan is a thin wrapper that counts dbHits per Next call. It adds 1 dbHit per row fetched from the underlying scan operator.
InstrumentedScan is NOT safe for concurrent use.
func NewInstrumentedScan ¶
func NewInstrumentedScan(op exec.Operator, counter *DbHitsCounter) *InstrumentedScan
NewInstrumentedScan wraps op with a dbHit counter. Each successful Next call adds 1 to counter.
func (*InstrumentedScan) Close ¶
func (s *InstrumentedScan) Close() error
Close implements exec.Operator. It delegates to the inner operator.
func (*InstrumentedScan) Init ¶
func (s *InstrumentedScan) Init(ctx context.Context) error
Init implements exec.Operator. It delegates to the inner operator.
func (*InstrumentedScan) Next ¶
func (s *InstrumentedScan) Next(out *exec.Row) (bool, error)
Next implements exec.Operator. It delegates to the inner operator and on a successful (true, nil) return increments the dbHits counter by 1.
type OperatorStats ¶
type OperatorStats struct {
// Name is the display name assigned when the operator was wrapped.
Name string
// Rows is the number of rows produced by successful Next calls.
Rows uint64
// DbHits is the number of logical storage accesses (see [DbHitsCounter]).
DbHits uint64
// ElapsedNs is the total nanoseconds spent inside Next across all calls.
ElapsedNs int64
}
OperatorStats accumulates execution statistics for one operator.
type ProfileReport ¶
type ProfileReport struct {
// Operators holds per-operator statistics in the order they were added.
Operators []OperatorStats
// TotalRows is the sum of all operator row counts.
TotalRows uint64
// TotalDbHits is the sum of all operator dbHits.
TotalDbHits uint64
// ElapsedMs is the total wall-clock time in milliseconds.
ElapsedMs float64
}
ProfileReport is the textual PROFILE output collected after draining a pipeline instrumented with ProfiledOperator wrappers.
type ProfiledOperator ¶
type ProfiledOperator struct {
// contains filtered or unexported fields
}
ProfiledOperator wraps an exec.Operator and records per-call statistics. It implements exec.Operator.
ProfiledOperator is NOT safe for concurrent use.
func NewProfiledOperator ¶
func NewProfiledOperator(op exec.Operator, name string) *ProfiledOperator
NewProfiledOperator wraps op, assigning it the display name given by name.
func (*ProfiledOperator) Close ¶
func (p *ProfiledOperator) Close() error
Close implements exec.Operator. It delegates to the inner operator.
func (*ProfiledOperator) Init ¶
func (p *ProfiledOperator) Init(ctx context.Context) error
Init implements exec.Operator. It delegates to the inner operator.
func (*ProfiledOperator) Next ¶
func (p *ProfiledOperator) Next(out *exec.Row) (bool, error)
Next implements exec.Operator. It delegates to the inner operator, incrementing Rows on each (true, nil) return and accumulating elapsed time.
func (*ProfiledOperator) Stats ¶
func (p *ProfiledOperator) Stats() OperatorStats
Stats returns the accumulated statistics for this operator.