github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/base/metrics.go (about)

     1  // Copyright 2022 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package base
     6  
     7  import "time"
     8  
     9  // ThroughputMetric is used to measure the byte throughput of some component
    10  // that performs work in a single-threaded manner. The throughput can be
    11  // approximated by Bytes/(WorkDuration+IdleTime). The idle time is represented
    12  // separately, so that the user of this metric could approximate the peak
    13  // throughput as Bytes/WorkTime. The metric is designed to be cumulative (see
    14  // Merge).
    15  type ThroughputMetric struct {
    16  	// Bytes is the processes bytes by the component.
    17  	Bytes int64
    18  	// WorkDuration is the duration that the component spent doing work.
    19  	WorkDuration time.Duration
    20  	// IdleDuration is the duration that the component was idling, waiting for
    21  	// work.
    22  	IdleDuration time.Duration
    23  }
    24  
    25  // Merge accumulates the information from another throughput metric.
    26  func (tm *ThroughputMetric) Merge(x ThroughputMetric) {
    27  	tm.Bytes += x.Bytes
    28  	tm.WorkDuration += x.WorkDuration
    29  	tm.IdleDuration += x.IdleDuration
    30  }
    31  
    32  // Subtract subtracts the information from another ThroughputMetric
    33  func (tm *ThroughputMetric) Subtract(x ThroughputMetric) {
    34  	tm.Bytes -= x.Bytes
    35  	tm.WorkDuration -= x.WorkDuration
    36  	tm.IdleDuration -= x.IdleDuration
    37  }
    38  
    39  // PeakRate returns the approximate peak rate if there was no idling.
    40  func (tm *ThroughputMetric) PeakRate() int64 {
    41  	if tm.Bytes == 0 {
    42  		return 0
    43  	}
    44  	return int64((float64(tm.Bytes) / float64(tm.WorkDuration)) * float64(time.Second))
    45  }
    46  
    47  // Rate returns the observed rate.
    48  func (tm *ThroughputMetric) Rate() int64 {
    49  	if tm.Bytes == 0 {
    50  		return 0
    51  	}
    52  	return int64((float64(tm.Bytes) / float64(tm.WorkDuration+tm.IdleDuration)) *
    53  		float64(time.Second))
    54  }
    55  
    56  // Utilization returns a percent [0, 1.0] indicating the percent of time
    57  // work was performed.
    58  func (tm *ThroughputMetric) Utilization() float64 {
    59  	if tm.WorkDuration == 0 {
    60  		return 0
    61  	}
    62  	return float64(tm.WorkDuration) / float64(tm.WorkDuration+tm.IdleDuration)
    63  }
    64  
    65  // GaugeSampleMetric is used to measure a gauge value (e.g. queue length) by
    66  // accumulating samples of that gauge.
    67  type GaugeSampleMetric struct {
    68  	// The sum of all the samples.
    69  	sampleSum int64
    70  	// The number of samples.
    71  	count int64
    72  }
    73  
    74  // AddSample adds the given sample.
    75  func (gsm *GaugeSampleMetric) AddSample(sample int64) {
    76  	gsm.sampleSum += sample
    77  	gsm.count++
    78  }
    79  
    80  // Merge accumulates the information from another gauge metric.
    81  func (gsm *GaugeSampleMetric) Merge(x GaugeSampleMetric) {
    82  	gsm.sampleSum += x.sampleSum
    83  	gsm.count += x.count
    84  }
    85  
    86  // Subtract subtracts the information from another gauge metric.
    87  func (gsm *GaugeSampleMetric) Subtract(x GaugeSampleMetric) {
    88  	gsm.sampleSum -= x.sampleSum
    89  	gsm.count -= x.count
    90  }
    91  
    92  // Mean returns the mean value.
    93  func (gsm *GaugeSampleMetric) Mean() float64 {
    94  	if gsm.count == 0 {
    95  		return 0
    96  	}
    97  	return float64(gsm.sampleSum) / float64(gsm.count)
    98  }