...

Source file src/cuelang.org/go/cue/stats/stats.go

Documentation: cuelang.org/go/cue/stats

     1  // Copyright 2022 CUE Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package stats is an experimental package for getting statistics on CUE
    16  // evaluations.
    17  package stats
    18  
    19  import (
    20  	"strings"
    21  	"text/template"
    22  )
    23  
    24  // Counts holds counters for key events during a CUE evaluation.
    25  //
    26  // This is an experimental type and the contents may change without notice.
    27  type Counts struct {
    28  	// Operation counters
    29  	//
    30  	// These counters account for several key operations.
    31  
    32  	// Unifications counts the number of calls to adt.Unify
    33  	Unifications int64
    34  
    35  	// Disjuncts indicates the number of total disjuncts processed as part
    36  	// of a Unify operation. A unification with no | operator counts as a
    37  	// single disjunct, so Disjuncts is always greater than or equal to the
    38  	// number of Unifications.
    39  	//
    40  	// If Disjuncts is much larger than Unification, this may indicate room
    41  	// for optimization. In particular, most practical uses of disjunctions
    42  	// should allow for near-linear processing.
    43  	Disjuncts int64
    44  
    45  	// Conjuncts is an estimate of the number of conjunctions processed during
    46  	// the calls to Unify. This includes the conjuncts added in the compilation
    47  	// phase as well as the derivative conjuncts inserted from other nodes
    48  	// after following references.
    49  	//
    50  	// A number of Conjuncts much larger than Disjuncts may indicate non-linear
    51  	// algorithmic behavior.
    52  	Conjuncts int64
    53  
    54  	// Buffer counters
    55  	//
    56  	// Each unification and disjunct operation is associated with an object
    57  	// with temporary buffers. Reuse of this buffer is critical for performance.
    58  	// The following counters track this.
    59  
    60  	Freed    int64 // Number of buffers returned to the free pool.
    61  	Reused   int64 // Number of times a buffer is reused instead of allocated.
    62  	Allocs   int64 // Total number of allocated buffer objects.
    63  	Retained int64 // Number of times a buffer is retained upon finalization.
    64  }
    65  
    66  // TODO: None of the methods below protect against overflows or underflows.
    67  // If those start happening in practice, or if the counters get large enough,
    68  // add checks on each of the operations.
    69  
    70  func (c *Counts) Add(other Counts) {
    71  	c.Unifications += other.Unifications
    72  	c.Conjuncts += other.Conjuncts
    73  	c.Disjuncts += other.Disjuncts
    74  
    75  	c.Freed += other.Freed
    76  	c.Retained += other.Retained
    77  	c.Reused += other.Reused
    78  	c.Allocs += other.Allocs
    79  }
    80  
    81  func (c Counts) Since(start Counts) Counts {
    82  	c.Unifications -= start.Unifications
    83  	c.Conjuncts -= start.Conjuncts
    84  	c.Disjuncts -= start.Disjuncts
    85  
    86  	c.Freed -= start.Freed
    87  	c.Retained -= start.Retained
    88  	c.Reused -= start.Reused
    89  	c.Allocs -= start.Allocs
    90  
    91  	return c
    92  }
    93  
    94  // Leaks reports the number of nodeContext structs leaked. These are typically
    95  // benign, as they will just be garbage collected, as long as the pointer from
    96  // the original nodes has been eliminated or the original nodes are also not
    97  // referred to. But Leaks may have notable impact on performance, and thus
    98  // should be avoided.
    99  func (s Counts) Leaks() int64 {
   100  	return s.Allocs + s.Reused - s.Freed
   101  }
   102  
   103  var stats = template.Must(template.New("stats").Parse(`{{"" -}}
   104  
   105  Leaks:  {{.Leaks}}
   106  Freed:  {{.Freed}}
   107  Reused: {{.Reused}}
   108  Allocs: {{.Allocs}}
   109  Retain: {{.Retained}}
   110  
   111  Unifications: {{.Unifications}}
   112  Conjuncts:    {{.Conjuncts}}
   113  Disjuncts:    {{.Disjuncts}}`))
   114  
   115  func (s Counts) String() string {
   116  	buf := &strings.Builder{}
   117  	err := stats.Execute(buf, s)
   118  	if err != nil {
   119  		panic(err)
   120  	}
   121  	return buf.String()
   122  }
   123  

View as plain text