mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 06:27:05 +00:00
Add timing ratio histograms
Following is the result of benchmarking the two kinds of histograms on my laptop. % go test -benchmem -run=^$ -bench Histogram . goos: darwin goarch: amd64 pkg: k8s.io/apiserver/pkg/util/flowcontrol/metrics cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz BenchmarkSampleAndWaterMarkHistogramsVecEltSafeEarly-16 980143 1230 ns/op 0 B/op 0 allocs/op BenchmarkSampleAndWaterMarkHistogramsVecEltSafeLate-16 932380 1216 ns/op 0 B/op 0 allocs/op BenchmarkTimingRatioHistogram-16 12665247 94.13 ns/op 0 B/op 0 allocs/op BenchmarkTimingRatioHistogramVecElementSimple-16 11015806 100.4 ns/op 0 B/op 0 allocs/op BenchmarkTimingRatioHistogramVecElementSafeEarly-16 7142589 172.0 ns/op 0 B/op 0 allocs/op BenchmarkTimingRatioHistogramVecElementSafeLate-16 11487517 96.67 ns/op 0 B/op 0 allocs/op PASS ok k8s.io/apiserver/pkg/util/flowcontrol/metrics 7.718s
This commit is contained in:
parent
5503bb0570
commit
8039f9d600
@ -120,3 +120,71 @@ func getHistogramCount(registry compbasemetrics.KubeRegistry, metricName string)
|
|||||||
}
|
}
|
||||||
return 0, errMetricNotFound
|
return 0, errMetricNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkSampleAndWaterMarkHistogramsVecEltSafeEarly(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
now := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(now)
|
||||||
|
thv := NewSampleAndWaterMarkHistogramsVec(clk, time.Millisecond,
|
||||||
|
&compbasemetrics.HistogramOpts{
|
||||||
|
Namespace: "testns",
|
||||||
|
Subsystem: "testsubsys",
|
||||||
|
Name: "samplehist",
|
||||||
|
Help: "Me",
|
||||||
|
Buckets: []float64{1, 2, 4, 8, 16, 32},
|
||||||
|
},
|
||||||
|
&compbasemetrics.HistogramOpts{
|
||||||
|
Namespace: "testns",
|
||||||
|
Subsystem: "testsubsys",
|
||||||
|
Name: "markhist",
|
||||||
|
Help: "Me",
|
||||||
|
Buckets: []float64{1, 2, 4, 8, 16, 32},
|
||||||
|
},
|
||||||
|
[]string{"labelname"})
|
||||||
|
th := thv.NewForLabelValuesSafe(0, 3, []string{"labelvalue"})
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
registry.MustRegister(thv.metrics()...)
|
||||||
|
var x int
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
delta := (i % 6) + 1
|
||||||
|
now = now.Add(time.Duration(delta) * time.Millisecond)
|
||||||
|
clk.SetTime(now)
|
||||||
|
th.Set(float64(x))
|
||||||
|
x = (x + i) % 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSampleAndWaterMarkHistogramsVecEltSafeLate(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
now := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(now)
|
||||||
|
thv := NewSampleAndWaterMarkHistogramsVec(clk, time.Millisecond,
|
||||||
|
&compbasemetrics.HistogramOpts{
|
||||||
|
Namespace: "testns",
|
||||||
|
Subsystem: "testsubsys",
|
||||||
|
Name: "samplehist",
|
||||||
|
Help: "Me",
|
||||||
|
Buckets: []float64{1, 2, 4, 8, 16, 32},
|
||||||
|
},
|
||||||
|
&compbasemetrics.HistogramOpts{
|
||||||
|
Namespace: "testns",
|
||||||
|
Subsystem: "testsubsys",
|
||||||
|
Name: "markhist",
|
||||||
|
Help: "Me",
|
||||||
|
Buckets: []float64{1, 2, 4, 8, 16, 32},
|
||||||
|
},
|
||||||
|
[]string{"labelname"})
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
registry.MustRegister(thv.metrics()...)
|
||||||
|
th := thv.NewForLabelValuesSafe(0, 3, []string{"labelvalue"})
|
||||||
|
var x int
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
delta := (i % 6) + 1
|
||||||
|
now = now.Add(time.Duration(delta) * time.Millisecond)
|
||||||
|
clk.SetTime(now)
|
||||||
|
th.Set(float64(x))
|
||||||
|
x = (x + i) % 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
compbasemetrics "k8s.io/component-base/metrics"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TimingRatioHistogram is essentially a gauge for a ratio where the client
|
||||||
|
// independently controls the numerator and denominator.
|
||||||
|
// When scraped it produces a histogram of samples of the ratio
|
||||||
|
// taken at the end of every nanosecond.
|
||||||
|
// `*TimingRatioHistogram` implements both Registerable and RatioedGauge.
|
||||||
|
type TimingRatioHistogram struct {
|
||||||
|
// The implementation is layered on TimingHistogram,
|
||||||
|
// adding the division by an occasionally adjusted denominator.
|
||||||
|
|
||||||
|
// Registerable is the registerable aspect.
|
||||||
|
// That is the registerable aspect of the underlying TimingHistogram.
|
||||||
|
compbasemetrics.Registerable
|
||||||
|
|
||||||
|
// timingRatioHistogramInner implements the RatioedGauge aspect.
|
||||||
|
timingRatioHistogramInner
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimingRatioHistogramOpts is the constructor parameters of a TimingRatioHistogram.
|
||||||
|
// The `TimingHistogramOpts.InitialValue` is the initial numerator.
|
||||||
|
type TimingRatioHistogramOpts struct {
|
||||||
|
compbasemetrics.TimingHistogramOpts
|
||||||
|
InitialDenominator float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// timingRatioHistogramInner implements the instrumentation aspect
|
||||||
|
type timingRatioHistogramInner struct {
|
||||||
|
nowFunc func() time.Time
|
||||||
|
getGaugeOfRatio func() Gauge
|
||||||
|
sync.Mutex
|
||||||
|
// access only with mutex locked
|
||||||
|
numerator, denominator float64
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ RatioedGauge = &timingRatioHistogramInner{}
|
||||||
|
var _ RatioedGauge = &TimingRatioHistogram{}
|
||||||
|
var _ compbasemetrics.Registerable = &TimingRatioHistogram{}
|
||||||
|
|
||||||
|
// NewTimingHistogram returns an object which is TimingHistogram-like. However, nothing
|
||||||
|
// will be measured until the histogram is registered in at least one registry.
|
||||||
|
func NewTimingRatioHistogram(opts *TimingRatioHistogramOpts) *TimingRatioHistogram {
|
||||||
|
return NewTestableTimingRatioHistogram(time.Now, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTestableTimingHistogram adds injection of the clock
|
||||||
|
func NewTestableTimingRatioHistogram(nowFunc func() time.Time, opts *TimingRatioHistogramOpts) *TimingRatioHistogram {
|
||||||
|
ratioedOpts := opts.TimingHistogramOpts
|
||||||
|
ratioedOpts.InitialValue /= opts.InitialDenominator
|
||||||
|
th := compbasemetrics.NewTestableTimingHistogram(nowFunc, &ratioedOpts)
|
||||||
|
return &TimingRatioHistogram{
|
||||||
|
Registerable: th,
|
||||||
|
timingRatioHistogramInner: timingRatioHistogramInner{
|
||||||
|
nowFunc: nowFunc,
|
||||||
|
getGaugeOfRatio: func() Gauge { return th },
|
||||||
|
numerator: opts.InitialValue,
|
||||||
|
denominator: opts.InitialDenominator,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trh *timingRatioHistogramInner) Set(numerator float64) {
|
||||||
|
trh.Lock()
|
||||||
|
defer trh.Unlock()
|
||||||
|
trh.numerator = numerator
|
||||||
|
ratio := numerator / trh.denominator
|
||||||
|
trh.getGaugeOfRatio().Set(ratio)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trh *timingRatioHistogramInner) Add(deltaNumerator float64) {
|
||||||
|
trh.Lock()
|
||||||
|
defer trh.Unlock()
|
||||||
|
numerator := trh.numerator + deltaNumerator
|
||||||
|
trh.numerator = numerator
|
||||||
|
ratio := numerator / trh.denominator
|
||||||
|
trh.getGaugeOfRatio().Set(ratio)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trh *timingRatioHistogramInner) Sub(deltaNumerator float64) {
|
||||||
|
trh.Add(-deltaNumerator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trh *timingRatioHistogramInner) Inc() {
|
||||||
|
trh.Add(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trh *timingRatioHistogramInner) Dec() {
|
||||||
|
trh.Add(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trh *timingRatioHistogramInner) SetToCurrentTime() {
|
||||||
|
trh.Set(float64(trh.nowFunc().Sub(time.Unix(0, 0))))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (trh *timingRatioHistogramInner) SetDenominator(denominator float64) {
|
||||||
|
trh.Lock()
|
||||||
|
defer trh.Unlock()
|
||||||
|
trh.denominator = denominator
|
||||||
|
ratio := trh.numerator / denominator
|
||||||
|
trh.getGaugeOfRatio().Set(ratio)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext allows the normal TimingHistogram metric to pass in context.
|
||||||
|
// The context is no-op at the current level of development.
|
||||||
|
func (trh *timingRatioHistogramInner) WithContext(ctx context.Context) RatioedGauge {
|
||||||
|
return trh
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimingRatioHistogramVec is a collection of TimingRatioHistograms that differ
|
||||||
|
// only in label values.
|
||||||
|
// `*TimingRatioHistogramVec` implements both Registerable and RatioedGaugeVec.
|
||||||
|
type TimingRatioHistogramVec struct {
|
||||||
|
// promote only the Registerable methods
|
||||||
|
compbasemetrics.Registerable
|
||||||
|
// delegate is TimingHistograms of the ratio
|
||||||
|
delegate compbasemetrics.GaugeVecMetric
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ RatioedGaugeVec = &TimingRatioHistogramVec{}
|
||||||
|
var _ compbasemetrics.Registerable = &TimingRatioHistogramVec{}
|
||||||
|
|
||||||
|
// NewTimingHistogramVec constructs a new vector.
|
||||||
|
// `opts.InitialValue` is the initial ratio, but this applies
|
||||||
|
// only for the tiny period of time until NewForLabelValuesSafe sets
|
||||||
|
// the ratio based on the given initial numerator and denominator.
|
||||||
|
// Thus there is a tiny splinter of time during member construction when
|
||||||
|
// its underlying TimingHistogram is given the initial numerator rather than
|
||||||
|
// the initial ratio (which is obviously a non-issue when both are zero).
|
||||||
|
// Note the difficulties associated with extracting a member
|
||||||
|
// before registering the vector.
|
||||||
|
func NewTimingRatioHistogramVec(opts *compbasemetrics.TimingHistogramOpts, labelNames ...string) *TimingRatioHistogramVec {
|
||||||
|
return NewTestableTimingRatioHistogramVec(time.Now, opts, labelNames...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTestableTimingHistogramVec adds injection of the clock.
|
||||||
|
func NewTestableTimingRatioHistogramVec(nowFunc func() time.Time, opts *compbasemetrics.TimingHistogramOpts, labelNames ...string) *TimingRatioHistogramVec {
|
||||||
|
delegate := compbasemetrics.NewTestableTimingHistogramVec(nowFunc, opts, labelNames)
|
||||||
|
return &TimingRatioHistogramVec{
|
||||||
|
Registerable: delegate,
|
||||||
|
delegate: delegate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *TimingRatioHistogramVec) metrics() Registerables {
|
||||||
|
return Registerables{v}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForLabelValuesChecked will return an error if this vec is not hidden and not yet registered
|
||||||
|
// or there is a syntactic problem with the labelValues.
|
||||||
|
func (v *TimingRatioHistogramVec) NewForLabelValuesChecked(initialNumerator, initialDenominator float64, labelValues []string) (RatioedGauge, error) {
|
||||||
|
underMember, err := v.delegate.WithLabelValuesChecked(labelValues...)
|
||||||
|
if err != nil {
|
||||||
|
return noopRatioed{}, err
|
||||||
|
}
|
||||||
|
underMember.Set(initialNumerator / initialDenominator)
|
||||||
|
return &timingRatioHistogramInner{
|
||||||
|
getGaugeOfRatio: func() Gauge { return underMember },
|
||||||
|
numerator: initialNumerator,
|
||||||
|
denominator: initialDenominator,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForLabelValuesSafe is the same as NewForLabelValuesChecked in cases where that does not
|
||||||
|
// return an error. When the unsafe version returns an error due to the vector not being
|
||||||
|
// registered yet, the safe version returns an object that implements its methods
|
||||||
|
// by looking up the relevant vector member in each call (thus getting a non-noop after registration).
|
||||||
|
// In the other error cases the object returned here is a noop.
|
||||||
|
func (v *TimingRatioHistogramVec) NewForLabelValuesSafe(initialNumerator, initialDenominator float64, labelValues []string) RatioedGauge {
|
||||||
|
tro, err := v.NewForLabelValuesChecked(initialNumerator, initialDenominator, labelValues)
|
||||||
|
if err == nil {
|
||||||
|
return tro
|
||||||
|
}
|
||||||
|
if !compbasemetrics.ErrIsNotRegistered(err) {
|
||||||
|
klog.ErrorS(err, "Failed to extract TimingRatioHistogramVec member, using noop instead", "vectorname", v.FQName(), "labelValues", labelValues)
|
||||||
|
return tro
|
||||||
|
}
|
||||||
|
// At this point we know v.NewForLabelValuesChecked(..) returns a permanent noop,
|
||||||
|
// which we precisely want to avoid using. Instead, make our own gauge that
|
||||||
|
// fetches the element on every Set.
|
||||||
|
return &timingRatioHistogramInner{
|
||||||
|
getGaugeOfRatio: func() Gauge { return v.delegate.WithLabelValues(labelValues...) },
|
||||||
|
numerator: initialNumerator,
|
||||||
|
denominator: initialDenominator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type noopRatioed struct{}
|
||||||
|
|
||||||
|
func (noopRatioed) Set(float64) {}
|
||||||
|
func (noopRatioed) Add(float64) {}
|
||||||
|
func (noopRatioed) Sub(float64) {}
|
||||||
|
func (noopRatioed) Inc() {}
|
||||||
|
func (noopRatioed) Dec() {}
|
||||||
|
func (noopRatioed) SetToCurrentTime() {}
|
||||||
|
func (noopRatioed) SetDenominator(float64) {}
|
||||||
|
|
||||||
|
func (v *TimingRatioHistogramVec) Reset() {
|
||||||
|
v.delegate.Reset()
|
||||||
|
}
|
@ -0,0 +1,242 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
compbasemetrics "k8s.io/component-base/metrics"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
testclock "k8s.io/utils/clock/testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTimingRatioHistogramVecElementSimple(t *testing.T) {
|
||||||
|
testHistogramName := "vec_element_simple"
|
||||||
|
t0 := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(t0)
|
||||||
|
buckets := []float64{0, 1}
|
||||||
|
vec := NewTestableTimingRatioHistogramVec(clk.Now,
|
||||||
|
&compbasemetrics.TimingHistogramOpts{Name: testHistogramName, Buckets: buckets},
|
||||||
|
"alabel",
|
||||||
|
)
|
||||||
|
toRegister := vec.metrics()
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
for _, reg := range toRegister {
|
||||||
|
registry.MustRegister(reg)
|
||||||
|
}
|
||||||
|
tro, err := vec.NewForLabelValuesChecked(0, 1, []string{"avalue"})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
exerciseTimingRatioHistogram(t, testHistogramName, t0, clk, registry, tro)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimingRatioHistogramVecElementSafeEarly(t *testing.T) {
|
||||||
|
testHistogramName := "vec_element_safe_early"
|
||||||
|
t0 := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(t0)
|
||||||
|
buckets := []float64{0, 1}
|
||||||
|
vec := NewTestableTimingRatioHistogramVec(clk.Now,
|
||||||
|
&compbasemetrics.TimingHistogramOpts{Name: testHistogramName, Buckets: buckets},
|
||||||
|
"alabel",
|
||||||
|
)
|
||||||
|
tro := vec.NewForLabelValuesSafe(0, 1, []string{"avalue"})
|
||||||
|
toRegister := vec.metrics()
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
for _, reg := range toRegister {
|
||||||
|
registry.MustRegister(reg)
|
||||||
|
}
|
||||||
|
exerciseTimingRatioHistogram(t, testHistogramName, t0, clk, registry, tro)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimingRatioHistogramVecElementSafeLate(t *testing.T) {
|
||||||
|
testHistogramName := "vec_element_safe_late"
|
||||||
|
t0 := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(t0)
|
||||||
|
buckets := []float64{0, 1}
|
||||||
|
vec := NewTestableTimingRatioHistogramVec(clk.Now,
|
||||||
|
&compbasemetrics.TimingHistogramOpts{Name: testHistogramName, Buckets: buckets},
|
||||||
|
"alabel",
|
||||||
|
)
|
||||||
|
toRegister := vec.metrics()
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
for _, reg := range toRegister {
|
||||||
|
registry.MustRegister(reg)
|
||||||
|
}
|
||||||
|
tro := vec.NewForLabelValuesSafe(0, 1, []string{"avalue"})
|
||||||
|
exerciseTimingRatioHistogram(t, testHistogramName, t0, clk, registry, tro)
|
||||||
|
}
|
||||||
|
|
||||||
|
// exerciseTimingRatioHistogram does a rough behavioral test of a
|
||||||
|
// RatioedObserver. A fake clock is used, and the exercise consists
|
||||||
|
// of repeatedly changing that fake clock by an amount of time chosen
|
||||||
|
// uniformly at random from a range that goes from a little negative
|
||||||
|
// to somewhat more than two milliseconds. The negative changes are
|
||||||
|
// included because small negative changes have been observed in real
|
||||||
|
// monotonic clock readings (see issue #96459) and we want to test
|
||||||
|
// that they are properly tolerated. The designed toleration is to
|
||||||
|
// pretend that the clock did not change, until it resumes net forward
|
||||||
|
// progress. The exercise checks that the count in the observer is
|
||||||
|
// correct at each step. The observer is expected to get one
|
||||||
|
// observation at the end of each nanosecond.
|
||||||
|
func exerciseTimingRatioHistogram(t *testing.T, histogramName string, t0 time.Time, clk *testclock.FakePassiveClock, registry compbasemetrics.KubeRegistry, tro RatioedGauge) {
|
||||||
|
samplingPeriod := time.Nanosecond
|
||||||
|
steppingPeriod := time.Millisecond
|
||||||
|
tro.Set(1)
|
||||||
|
// `dt` is the admitted cumulative difference in fake time
|
||||||
|
// since the start of the test. "admitted" means this is
|
||||||
|
// never allowed to decrease, which matches the designed
|
||||||
|
// toleration for negative monotonic clock changes.
|
||||||
|
var dt time.Duration
|
||||||
|
// `t1` is the current fake time
|
||||||
|
t1 := t0.Add(dt)
|
||||||
|
klog.Infof("Expect about %v warnings about time going backwards; this is fake time deliberately misbehaving.", (numIterations*ddtOffsetCentiPeriods)/ddtRangeCentiPeriods)
|
||||||
|
t.Logf("t0=%s", t0)
|
||||||
|
for i := 0; i < numIterations; i++ {
|
||||||
|
// `ddt` is the next step to take in fake time
|
||||||
|
ddt := time.Duration(rand.Intn(ddtRangeCentiPeriods)-ddtOffsetCentiPeriods) * steppingPeriod / 100
|
||||||
|
t1 = t1.Add(ddt)
|
||||||
|
diff := t1.Sub(t0)
|
||||||
|
if diff > dt {
|
||||||
|
dt = diff
|
||||||
|
}
|
||||||
|
clk.SetTime(t1)
|
||||||
|
tro.Set(1)
|
||||||
|
expectedCount := int64(dt / samplingPeriod)
|
||||||
|
actualCount, err := getHistogramCount(registry, histogramName)
|
||||||
|
if err != nil && !(err == errMetricNotFound && expectedCount == 0) {
|
||||||
|
t.Fatalf("For t0=%s, t1=%s, failed to getHistogramCount: %#+v", t0, t1, err)
|
||||||
|
}
|
||||||
|
t.Logf("For i=%d, ddt=%s, t1=%s, diff=%s, dt=%s, count=%d", i, ddt, t1, diff, dt, actualCount)
|
||||||
|
if expectedCount != actualCount {
|
||||||
|
t.Errorf("For i=%d, t0=%s, ddt=%s, t1=%s, expectedCount=%d, actualCount=%d", i, t0, ddt, t1, expectedCount, actualCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTimingRatioHistogram(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
now := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(now)
|
||||||
|
th := NewTestableTimingRatioHistogram(clk.Now,
|
||||||
|
&TimingRatioHistogramOpts{
|
||||||
|
compbasemetrics.TimingHistogramOpts{
|
||||||
|
Namespace: "testns",
|
||||||
|
Subsystem: "testsubsys",
|
||||||
|
Name: "testhist",
|
||||||
|
Help: "Me",
|
||||||
|
Buckets: []float64{1, 2, 4, 8, 16, 32},
|
||||||
|
},
|
||||||
|
1})
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
registry.MustRegister(th)
|
||||||
|
var x int
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
delta := (i % 6) + 1
|
||||||
|
now = now.Add(time.Duration(delta) * time.Millisecond)
|
||||||
|
clk.SetTime(now)
|
||||||
|
th.Set(float64(x))
|
||||||
|
x = (x + i) % 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTimingRatioHistogramVecElementSimple(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
now := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(now)
|
||||||
|
thv := NewTestableTimingRatioHistogramVec(clk.Now,
|
||||||
|
&compbasemetrics.TimingHistogramOpts{
|
||||||
|
Namespace: "testns",
|
||||||
|
Subsystem: "testsubsys",
|
||||||
|
Name: "testhist",
|
||||||
|
Help: "Me",
|
||||||
|
Buckets: []float64{1, 2, 4, 8, 16, 32},
|
||||||
|
},
|
||||||
|
"labelname")
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
registry.MustRegister(thv.metrics()...)
|
||||||
|
th, err := thv.NewForLabelValuesChecked(0, 3, []string{"labelvalue"})
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
}
|
||||||
|
var x int
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
delta := (i % 6) + 1
|
||||||
|
now = now.Add(time.Duration(delta) * time.Millisecond)
|
||||||
|
clk.SetTime(now)
|
||||||
|
th.Set(float64(x))
|
||||||
|
x = (x + i) % 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTimingRatioHistogramVecElementSafeEarly(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
now := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(now)
|
||||||
|
thv := NewTestableTimingRatioHistogramVec(clk.Now,
|
||||||
|
&compbasemetrics.TimingHistogramOpts{
|
||||||
|
Namespace: "testns",
|
||||||
|
Subsystem: "testsubsys",
|
||||||
|
Name: "testhist",
|
||||||
|
Help: "Me",
|
||||||
|
Buckets: []float64{1, 2, 4, 8, 16, 32},
|
||||||
|
},
|
||||||
|
"labelname")
|
||||||
|
th := thv.NewForLabelValuesSafe(0, 3, []string{"labelvalue"})
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
registry.MustRegister(thv.metrics()...)
|
||||||
|
var x int
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
delta := (i % 6) + 1
|
||||||
|
now = now.Add(time.Duration(delta) * time.Millisecond)
|
||||||
|
clk.SetTime(now)
|
||||||
|
th.Set(float64(x))
|
||||||
|
x = (x + i) % 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTimingRatioHistogramVecElementSafeLate(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
now := time.Now()
|
||||||
|
clk := testclock.NewFakePassiveClock(now)
|
||||||
|
thv := NewTestableTimingRatioHistogramVec(clk.Now,
|
||||||
|
&compbasemetrics.TimingHistogramOpts{
|
||||||
|
Namespace: "testns",
|
||||||
|
Subsystem: "testsubsys",
|
||||||
|
Name: "testhist",
|
||||||
|
Help: "Me",
|
||||||
|
Buckets: []float64{1, 2, 4, 8, 16, 32},
|
||||||
|
},
|
||||||
|
"labelname")
|
||||||
|
registry := compbasemetrics.NewKubeRegistry()
|
||||||
|
registry.MustRegister(thv.metrics()...)
|
||||||
|
th := thv.NewForLabelValuesSafe(0, 3, []string{"labelvalue"})
|
||||||
|
var x int
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
delta := (i % 6) + 1
|
||||||
|
now = now.Add(time.Duration(delta) * time.Millisecond)
|
||||||
|
clk.SetTime(now)
|
||||||
|
th.Set(float64(x))
|
||||||
|
x = (x + i) % 60
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user