Line data Source code
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 2 : func (tm *ThroughputMetric) Merge(x ThroughputMetric) { 27 2 : tm.Bytes += x.Bytes 28 2 : tm.WorkDuration += x.WorkDuration 29 2 : tm.IdleDuration += x.IdleDuration 30 2 : } 31 : 32 : // Subtract subtracts the information from another ThroughputMetric 33 1 : func (tm *ThroughputMetric) Subtract(x ThroughputMetric) { 34 1 : tm.Bytes -= x.Bytes 35 1 : tm.WorkDuration -= x.WorkDuration 36 1 : tm.IdleDuration -= x.IdleDuration 37 1 : } 38 : 39 : // PeakRate returns the approximate peak rate if there was no idling. 40 1 : func (tm *ThroughputMetric) PeakRate() int64 { 41 1 : if tm.Bytes == 0 { 42 0 : return 0 43 0 : } 44 1 : return int64((float64(tm.Bytes) / float64(tm.WorkDuration)) * float64(time.Second)) 45 : } 46 : 47 : // Rate returns the observed rate. 48 1 : func (tm *ThroughputMetric) Rate() int64 { 49 1 : if tm.Bytes == 0 { 50 0 : return 0 51 0 : } 52 1 : return int64((float64(tm.Bytes) / float64(tm.WorkDuration+tm.IdleDuration)) * 53 1 : float64(time.Second)) 54 : } 55 : 56 : // Utilization returns a percent [0, 1.0] indicating the percent of time 57 : // work was performed. 58 1 : func (tm *ThroughputMetric) Utilization() float64 { 59 1 : if tm.WorkDuration == 0 { 60 1 : return 0 61 1 : } 62 0 : 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 2 : func (gsm *GaugeSampleMetric) AddSample(sample int64) { 76 2 : gsm.sampleSum += sample 77 2 : gsm.count++ 78 2 : } 79 : 80 : // Merge accumulates the information from another gauge metric. 81 2 : func (gsm *GaugeSampleMetric) Merge(x GaugeSampleMetric) { 82 2 : gsm.sampleSum += x.sampleSum 83 2 : gsm.count += x.count 84 2 : } 85 : 86 : // Subtract subtracts the information from another gauge metric. 87 1 : func (gsm *GaugeSampleMetric) Subtract(x GaugeSampleMetric) { 88 1 : gsm.sampleSum -= x.sampleSum 89 1 : gsm.count -= x.count 90 1 : } 91 : 92 : // Mean returns the mean value. 93 1 : func (gsm *GaugeSampleMetric) Mean() float64 { 94 1 : if gsm.count == 0 { 95 0 : return 0 96 0 : } 97 1 : return float64(gsm.sampleSum) / float64(gsm.count) 98 : }