github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/roachpb/app_stats.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package roachpb
    12  
    13  import (
    14  	"math"
    15  
    16  	"github.com/cockroachdb/errors"
    17  )
    18  
    19  // GetVariance retrieves the variance of the values.
    20  func (l *NumericStat) GetVariance(count int64) float64 {
    21  	return l.SquaredDiffs / (float64(count) - 1)
    22  }
    23  
    24  // Record updates the underlying running counts, incorporating the given value.
    25  // It follows Welford's algorithm (Technometrics, 1962). The running count must
    26  // be stored as it is required to finalize and retrieve the variance.
    27  func (l *NumericStat) Record(count int64, val float64) {
    28  	delta := val - l.Mean
    29  	l.Mean += delta / float64(count)
    30  	l.SquaredDiffs += delta * (val - l.Mean)
    31  }
    32  
    33  // Add combines b into this derived statistics.
    34  func (l *NumericStat) Add(b NumericStat, countA, countB int64) {
    35  	*l = AddNumericStats(*l, b, countA, countB)
    36  }
    37  
    38  // AlmostEqual compares two NumericStats between a window of size eps.
    39  func (l *NumericStat) AlmostEqual(b NumericStat, eps float64) bool {
    40  	return math.Abs(l.Mean-b.Mean) <= eps &&
    41  		math.Abs(l.SquaredDiffs-b.SquaredDiffs) <= eps
    42  }
    43  
    44  // AddNumericStats combines derived statistics.
    45  // Adapted from https://www.johndcook.com/blog/skewness_kurtosis/
    46  func AddNumericStats(a, b NumericStat, countA, countB int64) NumericStat {
    47  	total := float64(countA + countB)
    48  	delta := b.Mean - a.Mean
    49  
    50  	return NumericStat{
    51  		Mean: ((a.Mean * float64(countA)) + (b.Mean * float64(countB))) / total,
    52  		SquaredDiffs: (a.SquaredDiffs + b.SquaredDiffs) +
    53  			delta*delta*float64(countA)*float64(countB)/total,
    54  	}
    55  }
    56  
    57  // GetScrubbedCopy returns a copy of the given SensitiveInfo with its fields redacted
    58  // or omitted entirely. By default, fields are omitted: if a new field is
    59  // added to the SensitiveInfo proto, it must be added here to make it to the
    60  // reg cluster.
    61  func (si SensitiveInfo) GetScrubbedCopy() SensitiveInfo {
    62  	output := SensitiveInfo{}
    63  	output.LastErr = errors.Redact(si.LastErr)
    64  	// Not copying over MostRecentPlanDescription until we have an algorithm to scrub plan nodes.
    65  	return output
    66  }
    67  
    68  // Add combines other into this TxnStats.
    69  func (s *TxnStats) Add(other TxnStats) {
    70  	s.TxnTimeSec.Add(other.TxnTimeSec, s.TxnCount, other.TxnCount)
    71  	s.TxnCount += other.TxnCount
    72  	s.ImplicitCount += other.ImplicitCount
    73  	s.CommittedCount += other.CommittedCount
    74  }
    75  
    76  // Add combines other into this StatementStatistics.
    77  func (s *StatementStatistics) Add(other *StatementStatistics) {
    78  	s.FirstAttemptCount += other.FirstAttemptCount
    79  	if other.MaxRetries > s.MaxRetries {
    80  		s.MaxRetries = other.MaxRetries
    81  	}
    82  	s.NumRows.Add(other.NumRows, s.Count, other.Count)
    83  	s.ParseLat.Add(other.ParseLat, s.Count, other.Count)
    84  	s.PlanLat.Add(other.PlanLat, s.Count, other.Count)
    85  	s.RunLat.Add(other.RunLat, s.Count, other.Count)
    86  	s.ServiceLat.Add(other.ServiceLat, s.Count, other.Count)
    87  	s.OverheadLat.Add(other.OverheadLat, s.Count, other.Count)
    88  
    89  	if other.SensitiveInfo.LastErr != "" {
    90  		s.SensitiveInfo.LastErr = other.SensitiveInfo.LastErr
    91  	}
    92  
    93  	if s.SensitiveInfo.MostRecentPlanTimestamp.Before(other.SensitiveInfo.MostRecentPlanTimestamp) {
    94  		s.SensitiveInfo = other.SensitiveInfo
    95  	}
    96  
    97  	s.BytesRead += other.BytesRead
    98  	s.RowsRead += other.RowsRead
    99  	s.Count += other.Count
   100  }
   101  
   102  // AlmostEqual compares two StatementStatistics and their contained NumericStats
   103  // objects within an window of size eps.
   104  func (s *StatementStatistics) AlmostEqual(other *StatementStatistics, eps float64) bool {
   105  	return s.Count == other.Count &&
   106  		s.FirstAttemptCount == other.FirstAttemptCount &&
   107  		s.MaxRetries == other.MaxRetries &&
   108  		s.NumRows.AlmostEqual(other.NumRows, eps) &&
   109  		s.ParseLat.AlmostEqual(other.ParseLat, eps) &&
   110  		s.PlanLat.AlmostEqual(other.PlanLat, eps) &&
   111  		s.RunLat.AlmostEqual(other.RunLat, eps) &&
   112  		s.ServiceLat.AlmostEqual(other.ServiceLat, eps) &&
   113  		s.OverheadLat.AlmostEqual(other.OverheadLat, eps) &&
   114  		s.SensitiveInfo.Equal(other.SensitiveInfo) &&
   115  		s.BytesRead == other.BytesRead &&
   116  		s.RowsRead == other.RowsRead
   117  }