diff --git a/go.mod b/go.mod index 15e3dcc..ccc8438 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/VictoriaMetrics/metrics -require github.com/valyala/histogram v1.0.1 +require github.com/valyala/histogram v1.1.1 go 1.12 diff --git a/go.sum b/go.sum index 9dd64f0..3914873 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,4 @@ github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI= github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= -github.com/valyala/histogram v1.0.1 h1:FzA7n2Tz/wKRMejgu3PV1vw3htAklTjjuoI6z3d4KDg= -github.com/valyala/histogram v1.0.1/go.mod h1:lQy0xA4wUz2+IUnf97SivorsJIp8FxsnRd6x25q7Mto= +github.com/valyala/histogram v1.1.1 h1:uyye4sBNmRMkh/XBxr0FXNO8YxqgFgSxZ0ePSG3U3Uw= +github.com/valyala/histogram v1.1.1/go.mod h1:CZAr6gK9dbD7hYx2s8WSPh0p5x5wETjC+2b3PJVtEdg= diff --git a/vendor/github.com/valyala/fastrand/.travis.yml b/vendor/github.com/valyala/fastrand/.travis.yml new file mode 100644 index 0000000..336ccde --- /dev/null +++ b/vendor/github.com/valyala/fastrand/.travis.yml @@ -0,0 +1,16 @@ +language: go + +go: + - 1.7 + - 1.8 + +script: + # build test for supported platforms + - GOOS=linux go build + - GOOS=darwin go build + - GOOS=freebsd go build + - GOARCH=386 go build + + # run tests on a standard platform + - go test -v ./... + diff --git a/vendor/github.com/valyala/fastrand/LICENSE b/vendor/github.com/valyala/fastrand/LICENSE new file mode 100644 index 0000000..a2b05f6 --- /dev/null +++ b/vendor/github.com/valyala/fastrand/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Aliaksandr Valialkin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/valyala/fastrand/README.md b/vendor/github.com/valyala/fastrand/README.md new file mode 100644 index 0000000..3d384c6 --- /dev/null +++ b/vendor/github.com/valyala/fastrand/README.md @@ -0,0 +1,76 @@ +[![Build Status](https://travis-ci.org/valyala/fastrand.svg)](https://travis-ci.org/valyala/fastrand) +[![GoDoc](https://godoc.org/github.com/valyala/fastrand?status.svg)](http://godoc.org/github.com/valyala/fastrand) +[![Go Report](https://goreportcard.com/badge/github.com/valyala/fastrand)](https://goreportcard.com/report/github.com/valyala/fastrand) + + +# fastrand + +Fast pseudorandom number generator. + + +# Features + +- Optimized for speed. +- Performance scales on multiple CPUs. + +# How does it work? + +It abuses [sync.Pool](https://golang.org/pkg/sync/#Pool) for maintaining +"per-CPU" pseudorandom number generators. + +TODO: firgure out how to use real per-CPU pseudorandom number generators. + + +# Benchmark results + + +``` +$ GOMAXPROCS=1 go test -bench=. github.com/valyala/fastrand +goos: linux +goarch: amd64 +pkg: github.com/valyala/fastrand +BenchmarkUint32n 50000000 29.7 ns/op +BenchmarkRNGUint32n 200000000 6.50 ns/op +BenchmarkRNGUint32nWithLock 100000000 21.5 ns/op +BenchmarkMathRandInt31n 50000000 31.8 ns/op +BenchmarkMathRandRNGInt31n 100000000 17.9 ns/op +BenchmarkMathRandRNGInt31nWithLock 50000000 30.2 ns/op +PASS +ok github.com/valyala/fastrand 10.634s +``` + +``` +$ GOMAXPROCS=2 go test -bench=. github.com/valyala/fastrand +goos: linux +goarch: amd64 +pkg: github.com/valyala/fastrand +BenchmarkUint32n-2 100000000 17.6 ns/op +BenchmarkRNGUint32n-2 500000000 3.36 ns/op +BenchmarkRNGUint32nWithLock-2 50000000 32.0 ns/op +BenchmarkMathRandInt31n-2 20000000 51.2 ns/op +BenchmarkMathRandRNGInt31n-2 100000000 11.0 ns/op +BenchmarkMathRandRNGInt31nWithLock-2 20000000 91.0 ns/op +PASS +ok github.com/valyala/fastrand 9.543s +``` + +``` +$ GOMAXPROCS=4 go test -bench=. github.com/valyala/fastrand +goos: linux +goarch: amd64 +pkg: github.com/valyala/fastrand +BenchmarkUint32n-4 100000000 14.2 ns/op +BenchmarkRNGUint32n-4 500000000 3.30 ns/op +BenchmarkRNGUint32nWithLock-4 20000000 88.7 ns/op +BenchmarkMathRandInt31n-4 10000000 145 ns/op +BenchmarkMathRandRNGInt31n-4 200000000 8.35 ns/op +BenchmarkMathRandRNGInt31nWithLock-4 20000000 102 ns/op +PASS +ok github.com/valyala/fastrand 11.534s +``` + +As you can see, [fastrand.Uint32n](https://godoc.org/github.com/valyala/fastrand#Uint32n) +scales on multiple CPUs, while [rand.Int31n](https://golang.org/pkg/math/rand/#Int31n) +doesn't scale. Their performance is comparable on `GOMAXPROCS=1`, +but `fastrand.Uint32n` runs 3x faster than `rand.Int31n` on `GOMAXPROCS=2` +and 10x faster than `rand.Int31n` on `GOMAXPROCS=4`. diff --git a/vendor/github.com/valyala/fastrand/fastrand.go b/vendor/github.com/valyala/fastrand/fastrand.go new file mode 100644 index 0000000..3ea9177 --- /dev/null +++ b/vendor/github.com/valyala/fastrand/fastrand.go @@ -0,0 +1,74 @@ +// Package fastrand implements fast pesudorandom number generator +// that should scale well on multi-CPU systems. +// +// Use crypto/rand instead of this package for generating +// cryptographically secure random numbers. +package fastrand + +import ( + "sync" + "time" +) + +// Uint32 returns pseudorandom uint32. +// +// It is safe calling this function from concurrent goroutines. +func Uint32() uint32 { + v := rngPool.Get() + if v == nil { + v = &RNG{} + } + r := v.(*RNG) + x := r.Uint32() + rngPool.Put(r) + return x +} + +var rngPool sync.Pool + +// Uint32n returns pseudorandom uint32 in the range [0..maxN). +// +// It is safe calling this function from concurrent goroutines. +func Uint32n(maxN uint32) uint32 { + x := Uint32() + // See http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ + return uint32((uint64(x) * uint64(maxN)) >> 32) +} + +// RNG is a pseudorandom number generator. +// +// It is unsafe to call RNG methods from concurrent goroutines. +type RNG struct { + x uint32 +} + +// Uint32 returns pseudorandom uint32. +// +// It is unsafe to call this method from concurrent goroutines. +func (r *RNG) Uint32() uint32 { + for r.x == 0 { + r.x = getRandomUint32() + } + + // See https://en.wikipedia.org/wiki/Xorshift + x := r.x + x ^= x << 13 + x ^= x >> 17 + x ^= x << 5 + r.x = x + return x +} + +// Uint32n returns pseudorandom uint32 in the range [0..maxN). +// +// It is unsafe to call this method from concurrent goroutines. +func (r *RNG) Uint32n(maxN uint32) uint32 { + x := r.Uint32() + // See http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ + return uint32((uint64(x) * uint64(maxN)) >> 32) +} + +func getRandomUint32() uint32 { + x := time.Now().UnixNano() + return uint32((x >> 32) ^ x) +} diff --git a/vendor/github.com/valyala/fastrand/go.mod b/vendor/github.com/valyala/fastrand/go.mod new file mode 100644 index 0000000..958910b --- /dev/null +++ b/vendor/github.com/valyala/fastrand/go.mod @@ -0,0 +1 @@ +module github.com/valyala/fastrand diff --git a/vendor/github.com/valyala/histogram/LICENSE b/vendor/github.com/valyala/histogram/LICENSE new file mode 100644 index 0000000..902bcad --- /dev/null +++ b/vendor/github.com/valyala/histogram/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 Aliaksandr Valialkin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/valyala/histogram/README.md b/vendor/github.com/valyala/histogram/README.md new file mode 100644 index 0000000..6d4eb59 --- /dev/null +++ b/vendor/github.com/valyala/histogram/README.md @@ -0,0 +1,9 @@ +[![GoDoc](https://godoc.org/github.com/valyala/histogram?status.svg)](http://godoc.org/github.com/valyala/histogram) +[![Go Report](https://goreportcard.com/badge/github.com/valyala/histogram)](https://goreportcard.com/report/github.com/valyala/histogram) + + +# histogram + +Fast histograms for Go. + +See [docs](https://godoc.org/github.com/valyala/histogram). diff --git a/vendor/github.com/valyala/histogram/go.mod b/vendor/github.com/valyala/histogram/go.mod new file mode 100644 index 0000000..984efbe --- /dev/null +++ b/vendor/github.com/valyala/histogram/go.mod @@ -0,0 +1,5 @@ +module github.com/valyala/histogram + +go 1.12 + +require github.com/valyala/fastrand v1.0.0 diff --git a/vendor/github.com/valyala/histogram/go.sum b/vendor/github.com/valyala/histogram/go.sum new file mode 100644 index 0000000..2b3e848 --- /dev/null +++ b/vendor/github.com/valyala/histogram/go.sum @@ -0,0 +1,2 @@ +github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI= +github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= diff --git a/vendor/github.com/valyala/histogram/histogram.go b/vendor/github.com/valyala/histogram/histogram.go new file mode 100644 index 0000000..e90dd70 --- /dev/null +++ b/vendor/github.com/valyala/histogram/histogram.go @@ -0,0 +1,127 @@ +// Package histogram provides building blocks for fast histograms. +package histogram + +import ( + "math" + "sort" + "sync" + + "github.com/valyala/fastrand" +) + +var ( + infNeg = math.Inf(-1) + infPos = math.Inf(1) + nan = math.NaN() +) + +// Fast is a fast histogram. +// +// It cannot be used from concurrently running goroutines without +// external synchronization. +type Fast struct { + max float64 + min float64 + count uint64 + + a []float64 + tmp []float64 + rng fastrand.RNG +} + +// NewFast returns new fast histogram. +func NewFast() *Fast { + f := &Fast{} + f.Reset() + return f +} + +// Reset resets the histogram. +func (f *Fast) Reset() { + f.max = infNeg + f.min = infPos + f.count = 0 + if len(f.a) > 0 { + f.a = f.a[:0] + f.tmp = f.tmp[:0] + } else { + // Free up memory occupied by unused histogram. + f.a = nil + f.tmp = nil + } +} + +// Update updates the f with v. +func (f *Fast) Update(v float64) { + if v > f.max { + f.max = v + } + if v < f.min { + f.min = v + } + + f.count++ + if len(f.a) < maxSamples { + f.a = append(f.a, v) + return + } + if n := int(f.rng.Uint32n(uint32(f.count))); n < len(f.a) { + f.a[n] = v + } +} + +const maxSamples = 1000 + +// Quantile returns the quantile value for the given phi. +func (f *Fast) Quantile(phi float64) float64 { + f.tmp = append(f.tmp[:0], f.a...) + sort.Float64s(f.tmp) + return f.quantile(phi) +} + +// Quantiles appends quantile values to dst for the given phis. +func (f *Fast) Quantiles(dst, phis []float64) []float64 { + f.tmp = append(f.tmp[:0], f.a...) + sort.Float64s(f.tmp) + for _, phi := range phis { + q := f.quantile(phi) + dst = append(dst, q) + } + return dst +} + +func (f *Fast) quantile(phi float64) float64 { + if len(f.tmp) == 0 || math.IsNaN(phi) { + return nan + } + if phi <= 0 { + return f.min + } + if phi >= 1 { + return f.max + } + idx := uint(phi*float64(len(f.tmp)-1) + 0.5) + if idx >= uint(len(f.tmp)) { + idx = uint(len(f.tmp) - 1) + } + return f.tmp[idx] +} + +// GetFast returns a histogram from a pool. +func GetFast() *Fast { + v := fastPool.Get() + if v == nil { + return NewFast() + } + return v.(*Fast) +} + +// PutFast puts hf to the pool. +// +// hf cannot be used after this call. +func PutFast(f *Fast) { + f.Reset() + fastPool.Put(f) +} + +var fastPool sync.Pool diff --git a/vendor/modules.txt b/vendor/modules.txt new file mode 100644 index 0000000..b2bed9a --- /dev/null +++ b/vendor/modules.txt @@ -0,0 +1,4 @@ +# github.com/valyala/fastrand v1.0.0 +github.com/valyala/fastrand +# github.com/valyala/histogram v1.1.1 +github.com/valyala/histogram