Switch to github.com/golang/dep for vendoring
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
This commit is contained in:
parent
d6ab91be27
commit
8e5b17cf13
15431 changed files with 3971413 additions and 8881 deletions
198
vendor/google.golang.org/grpc/benchmark/stats/histogram.go
generated
vendored
Normal file
198
vendor/google.golang.org/grpc/benchmark/stats/histogram.go
generated
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
package stats
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Histogram accumulates values in the form of a histogram with
|
||||
// exponentially increased bucket sizes.
|
||||
type Histogram struct {
|
||||
// Count is the total number of values added to the histogram.
|
||||
Count int64
|
||||
// Sum is the sum of all the values added to the histogram.
|
||||
Sum int64
|
||||
// SumOfSquares is the sum of squares of all values.
|
||||
SumOfSquares int64
|
||||
// Min is the minimum of all the values added to the histogram.
|
||||
Min int64
|
||||
// Max is the maximum of all the values added to the histogram.
|
||||
Max int64
|
||||
// Buckets contains all the buckets of the histogram.
|
||||
Buckets []HistogramBucket
|
||||
|
||||
opts HistogramOptions
|
||||
logBaseBucketSize float64
|
||||
oneOverLogOnePlusGrowthFactor float64
|
||||
}
|
||||
|
||||
// HistogramOptions contains the parameters that define the histogram's buckets.
|
||||
// The first bucket of the created histogram (with index 0) contains [min, min+n)
|
||||
// where n = BaseBucketSize, min = MinValue.
|
||||
// Bucket i (i>=1) contains [min + n * m^(i-1), min + n * m^i), where m = 1+GrowthFactor.
|
||||
// The type of the values is int64.
|
||||
type HistogramOptions struct {
|
||||
// NumBuckets is the number of buckets.
|
||||
NumBuckets int
|
||||
// GrowthFactor is the growth factor of the buckets. A value of 0.1
|
||||
// indicates that bucket N+1 will be 10% larger than bucket N.
|
||||
GrowthFactor float64
|
||||
// BaseBucketSize is the size of the first bucket.
|
||||
BaseBucketSize float64
|
||||
// MinValue is the lower bound of the first bucket.
|
||||
MinValue int64
|
||||
}
|
||||
|
||||
// HistogramBucket represents one histogram bucket.
|
||||
type HistogramBucket struct {
|
||||
// LowBound is the lower bound of the bucket.
|
||||
LowBound float64
|
||||
// Count is the number of values in the bucket.
|
||||
Count int64
|
||||
}
|
||||
|
||||
// NewHistogram returns a pointer to a new Histogram object that was created
|
||||
// with the provided options.
|
||||
func NewHistogram(opts HistogramOptions) *Histogram {
|
||||
if opts.NumBuckets == 0 {
|
||||
opts.NumBuckets = 32
|
||||
}
|
||||
if opts.BaseBucketSize == 0.0 {
|
||||
opts.BaseBucketSize = 1.0
|
||||
}
|
||||
h := Histogram{
|
||||
Buckets: make([]HistogramBucket, opts.NumBuckets),
|
||||
Min: math.MaxInt64,
|
||||
Max: math.MinInt64,
|
||||
|
||||
opts: opts,
|
||||
logBaseBucketSize: math.Log(opts.BaseBucketSize),
|
||||
oneOverLogOnePlusGrowthFactor: 1 / math.Log(1+opts.GrowthFactor),
|
||||
}
|
||||
m := 1.0 + opts.GrowthFactor
|
||||
delta := opts.BaseBucketSize
|
||||
h.Buckets[0].LowBound = float64(opts.MinValue)
|
||||
for i := 1; i < opts.NumBuckets; i++ {
|
||||
h.Buckets[i].LowBound = float64(opts.MinValue) + delta
|
||||
delta = delta * m
|
||||
}
|
||||
return &h
|
||||
}
|
||||
|
||||
// Print writes textual output of the histogram values.
|
||||
func (h *Histogram) Print(w io.Writer) {
|
||||
avg := float64(h.Sum) / float64(h.Count)
|
||||
fmt.Fprintf(w, "Count: %d Min: %d Max: %d Avg: %.2f\n", h.Count, h.Min, h.Max, avg)
|
||||
fmt.Fprintf(w, "%s\n", strings.Repeat("-", 60))
|
||||
if h.Count <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
maxBucketDigitLen := len(strconv.FormatFloat(h.Buckets[len(h.Buckets)-1].LowBound, 'f', 6, 64))
|
||||
if maxBucketDigitLen < 3 {
|
||||
// For "inf".
|
||||
maxBucketDigitLen = 3
|
||||
}
|
||||
maxCountDigitLen := len(strconv.FormatInt(h.Count, 10))
|
||||
percentMulti := 100 / float64(h.Count)
|
||||
|
||||
accCount := int64(0)
|
||||
for i, b := range h.Buckets {
|
||||
fmt.Fprintf(w, "[%*f, ", maxBucketDigitLen, b.LowBound)
|
||||
if i+1 < len(h.Buckets) {
|
||||
fmt.Fprintf(w, "%*f)", maxBucketDigitLen, h.Buckets[i+1].LowBound)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%*s)", maxBucketDigitLen, "inf")
|
||||
}
|
||||
|
||||
accCount += b.Count
|
||||
fmt.Fprintf(w, " %*d %5.1f%% %5.1f%%", maxCountDigitLen, b.Count, float64(b.Count)*percentMulti, float64(accCount)*percentMulti)
|
||||
|
||||
const barScale = 0.1
|
||||
barLength := int(float64(b.Count)*percentMulti*barScale + 0.5)
|
||||
fmt.Fprintf(w, " %s\n", strings.Repeat("#", barLength))
|
||||
}
|
||||
}
|
||||
|
||||
// String returns the textual output of the histogram values as string.
|
||||
func (h *Histogram) String() string {
|
||||
var b bytes.Buffer
|
||||
h.Print(&b)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// Clear resets all the content of histogram.
|
||||
func (h *Histogram) Clear() {
|
||||
h.Count = 0
|
||||
h.Sum = 0
|
||||
h.SumOfSquares = 0
|
||||
h.Min = math.MaxInt64
|
||||
h.Max = math.MinInt64
|
||||
for i := range h.Buckets {
|
||||
h.Buckets[i].Count = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Opts returns a copy of the options used to create the Histogram.
|
||||
func (h *Histogram) Opts() HistogramOptions {
|
||||
return h.opts
|
||||
}
|
||||
|
||||
// Add adds a value to the histogram.
|
||||
func (h *Histogram) Add(value int64) error {
|
||||
bucket, err := h.findBucket(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.Buckets[bucket].Count++
|
||||
h.Count++
|
||||
h.Sum += value
|
||||
h.SumOfSquares += value * value
|
||||
if value < h.Min {
|
||||
h.Min = value
|
||||
}
|
||||
if value > h.Max {
|
||||
h.Max = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Histogram) findBucket(value int64) (int, error) {
|
||||
delta := float64(value - h.opts.MinValue)
|
||||
var b int
|
||||
if delta >= h.opts.BaseBucketSize {
|
||||
// b = log_{1+growthFactor} (delta / baseBucketSize) + 1
|
||||
// = log(delta / baseBucketSize) / log(1+growthFactor) + 1
|
||||
// = (log(delta) - log(baseBucketSize)) * (1 / log(1+growthFactor)) + 1
|
||||
b = int((math.Log(delta)-h.logBaseBucketSize)*h.oneOverLogOnePlusGrowthFactor + 1)
|
||||
}
|
||||
if b >= len(h.Buckets) {
|
||||
return 0, fmt.Errorf("no bucket for value: %d", value)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Merge takes another histogram h2, and merges its content into h.
|
||||
// The two histograms must be created by equivalent HistogramOptions.
|
||||
func (h *Histogram) Merge(h2 *Histogram) {
|
||||
if h.opts != h2.opts {
|
||||
log.Fatalf("failed to merge histograms, created by inequivalent options")
|
||||
}
|
||||
h.Count += h2.Count
|
||||
h.Sum += h2.Sum
|
||||
h.SumOfSquares += h2.SumOfSquares
|
||||
if h2.Min < h.Min {
|
||||
h.Min = h2.Min
|
||||
}
|
||||
if h2.Max > h.Max {
|
||||
h.Max = h2.Max
|
||||
}
|
||||
for i, b := range h2.Buckets {
|
||||
h.Buckets[i].Count += b.Count
|
||||
}
|
||||
}
|
116
vendor/google.golang.org/grpc/benchmark/stats/stats.go
generated
vendored
Normal file
116
vendor/google.golang.org/grpc/benchmark/stats/stats.go
generated
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
package stats
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Stats is a simple helper for gathering additional statistics like histogram
|
||||
// during benchmarks. This is not thread safe.
|
||||
type Stats struct {
|
||||
numBuckets int
|
||||
unit time.Duration
|
||||
min, max int64
|
||||
histogram *Histogram
|
||||
|
||||
durations durationSlice
|
||||
dirty bool
|
||||
}
|
||||
|
||||
type durationSlice []time.Duration
|
||||
|
||||
// NewStats creates a new Stats instance. If numBuckets is not positive,
|
||||
// the default value (16) will be used.
|
||||
func NewStats(numBuckets int) *Stats {
|
||||
if numBuckets <= 0 {
|
||||
numBuckets = 16
|
||||
}
|
||||
return &Stats{
|
||||
// Use one more bucket for the last unbounded bucket.
|
||||
numBuckets: numBuckets + 1,
|
||||
durations: make(durationSlice, 0, 100000),
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds an elapsed time per operation to the stats.
|
||||
func (stats *Stats) Add(d time.Duration) {
|
||||
stats.durations = append(stats.durations, d)
|
||||
stats.dirty = true
|
||||
}
|
||||
|
||||
// Clear resets the stats, removing all values.
|
||||
func (stats *Stats) Clear() {
|
||||
stats.durations = stats.durations[:0]
|
||||
stats.histogram = nil
|
||||
stats.dirty = false
|
||||
}
|
||||
|
||||
// maybeUpdate updates internal stat data if there was any newly added
|
||||
// stats since this was updated.
|
||||
func (stats *Stats) maybeUpdate() {
|
||||
if !stats.dirty {
|
||||
return
|
||||
}
|
||||
|
||||
stats.min = math.MaxInt64
|
||||
stats.max = 0
|
||||
for _, d := range stats.durations {
|
||||
if stats.min > int64(d) {
|
||||
stats.min = int64(d)
|
||||
}
|
||||
if stats.max < int64(d) {
|
||||
stats.max = int64(d)
|
||||
}
|
||||
}
|
||||
|
||||
// Use the largest unit that can represent the minimum time duration.
|
||||
stats.unit = time.Nanosecond
|
||||
for _, u := range []time.Duration{time.Microsecond, time.Millisecond, time.Second} {
|
||||
if stats.min <= int64(u) {
|
||||
break
|
||||
}
|
||||
stats.unit = u
|
||||
}
|
||||
|
||||
// Adjust the min/max according to the new unit.
|
||||
stats.min /= int64(stats.unit)
|
||||
stats.max /= int64(stats.unit)
|
||||
numBuckets := stats.numBuckets
|
||||
if n := int(stats.max - stats.min + 1); n < numBuckets {
|
||||
numBuckets = n
|
||||
}
|
||||
stats.histogram = NewHistogram(HistogramOptions{
|
||||
NumBuckets: numBuckets,
|
||||
// max-min(lower bound of last bucket) = (1 + growthFactor)^(numBuckets-2) * baseBucketSize.
|
||||
GrowthFactor: math.Pow(float64(stats.max-stats.min), 1/float64(numBuckets-2)) - 1,
|
||||
BaseBucketSize: 1.0,
|
||||
MinValue: stats.min})
|
||||
|
||||
for _, d := range stats.durations {
|
||||
stats.histogram.Add(int64(d / stats.unit))
|
||||
}
|
||||
|
||||
stats.dirty = false
|
||||
}
|
||||
|
||||
// Print writes textual output of the Stats.
|
||||
func (stats *Stats) Print(w io.Writer) {
|
||||
stats.maybeUpdate()
|
||||
|
||||
if stats.histogram == nil {
|
||||
fmt.Fprint(w, "Histogram (empty)\n")
|
||||
} else {
|
||||
fmt.Fprintf(w, "Histogram (unit: %s)\n", fmt.Sprintf("%v", stats.unit)[1:])
|
||||
stats.histogram.Print(w)
|
||||
}
|
||||
}
|
||||
|
||||
// String returns the textual output of the Stats as string.
|
||||
func (stats *Stats) String() string {
|
||||
var b bytes.Buffer
|
||||
stats.Print(&b)
|
||||
return b.String()
|
||||
}
|
191
vendor/google.golang.org/grpc/benchmark/stats/util.go
generated
vendored
Normal file
191
vendor/google.golang.org/grpc/benchmark/stats/util.go
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
|||
package stats
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
curB *testing.B
|
||||
curBenchName string
|
||||
curStats map[string]*Stats
|
||||
|
||||
orgStdout *os.File
|
||||
nextOutPos int
|
||||
|
||||
injectCond *sync.Cond
|
||||
injectDone chan struct{}
|
||||
)
|
||||
|
||||
// AddStats adds a new unnamed Stats instance to the current benchmark. You need
|
||||
// to run benchmarks by calling RunTestMain() to inject the stats to the
|
||||
// benchmark results. If numBuckets is not positive, the default value (16) will
|
||||
// be used. Please note that this calls b.ResetTimer() since it may be blocked
|
||||
// until the previous benchmark stats is printed out. So AddStats() should
|
||||
// typically be called at the very beginning of each benchmark function.
|
||||
func AddStats(b *testing.B, numBuckets int) *Stats {
|
||||
return AddStatsWithName(b, "", numBuckets)
|
||||
}
|
||||
|
||||
// AddStatsWithName adds a new named Stats instance to the current benchmark.
|
||||
// With this, you can add multiple stats in a single benchmark. You need
|
||||
// to run benchmarks by calling RunTestMain() to inject the stats to the
|
||||
// benchmark results. If numBuckets is not positive, the default value (16) will
|
||||
// be used. Please note that this calls b.ResetTimer() since it may be blocked
|
||||
// until the previous benchmark stats is printed out. So AddStatsWithName()
|
||||
// should typically be called at the very beginning of each benchmark function.
|
||||
func AddStatsWithName(b *testing.B, name string, numBuckets int) *Stats {
|
||||
var benchName string
|
||||
for i := 1; ; i++ {
|
||||
pc, _, _, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
panic("benchmark function not found")
|
||||
}
|
||||
p := strings.Split(runtime.FuncForPC(pc).Name(), ".")
|
||||
benchName = p[len(p)-1]
|
||||
if strings.HasPrefix(benchName, "Benchmark") {
|
||||
break
|
||||
}
|
||||
}
|
||||
procs := runtime.GOMAXPROCS(-1)
|
||||
if procs != 1 {
|
||||
benchName = fmt.Sprintf("%s-%d", benchName, procs)
|
||||
}
|
||||
|
||||
stats := NewStats(numBuckets)
|
||||
|
||||
if injectCond != nil {
|
||||
// We need to wait until the previous benchmark stats is printed out.
|
||||
injectCond.L.Lock()
|
||||
for curB != nil && curBenchName != benchName {
|
||||
injectCond.Wait()
|
||||
}
|
||||
|
||||
curB = b
|
||||
curBenchName = benchName
|
||||
curStats[name] = stats
|
||||
|
||||
injectCond.L.Unlock()
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
return stats
|
||||
}
|
||||
|
||||
// RunTestMain runs the tests with enabling injection of benchmark stats. It
|
||||
// returns an exit code to pass to os.Exit.
|
||||
func RunTestMain(m *testing.M) int {
|
||||
startStatsInjector()
|
||||
defer stopStatsInjector()
|
||||
return m.Run()
|
||||
}
|
||||
|
||||
// startStatsInjector starts stats injection to benchmark results.
|
||||
func startStatsInjector() {
|
||||
orgStdout = os.Stdout
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stdout = w
|
||||
nextOutPos = 0
|
||||
|
||||
resetCurBenchStats()
|
||||
|
||||
injectCond = sync.NewCond(&sync.Mutex{})
|
||||
injectDone = make(chan struct{})
|
||||
go func() {
|
||||
defer close(injectDone)
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Split(splitLines)
|
||||
for scanner.Scan() {
|
||||
injectStatsIfFinished(scanner.Text())
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// stopStatsInjector stops stats injection and restores os.Stdout.
|
||||
func stopStatsInjector() {
|
||||
os.Stdout.Close()
|
||||
<-injectDone
|
||||
injectCond = nil
|
||||
os.Stdout = orgStdout
|
||||
}
|
||||
|
||||
// splitLines is a split function for a bufio.Scanner that returns each line
|
||||
// of text, teeing texts to the original stdout even before each line ends.
|
||||
func splitLines(data []byte, eof bool) (advance int, token []byte, err error) {
|
||||
if eof && len(data) == 0 {
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
if i := bytes.IndexByte(data, '\n'); i >= 0 {
|
||||
orgStdout.Write(data[nextOutPos : i+1])
|
||||
nextOutPos = 0
|
||||
return i + 1, data[0:i], nil
|
||||
}
|
||||
|
||||
orgStdout.Write(data[nextOutPos:])
|
||||
nextOutPos = len(data)
|
||||
|
||||
if eof {
|
||||
// This is a final, non-terminated line. Return it.
|
||||
return len(data), data, nil
|
||||
}
|
||||
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
// injectStatsIfFinished prints out the stats if the current benchmark finishes.
|
||||
func injectStatsIfFinished(line string) {
|
||||
injectCond.L.Lock()
|
||||
defer injectCond.L.Unlock()
|
||||
|
||||
// We assume that the benchmark results start with the benchmark name.
|
||||
if curB == nil || !strings.HasPrefix(line, curBenchName) {
|
||||
return
|
||||
}
|
||||
|
||||
if !curB.Failed() {
|
||||
// Output all stats in alphabetical order.
|
||||
names := make([]string, 0, len(curStats))
|
||||
for name := range curStats {
|
||||
names = append(names, name)
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, name := range names {
|
||||
stats := curStats[name]
|
||||
// The output of stats starts with a header like "Histogram (unit: ms)"
|
||||
// followed by statistical properties and the buckets. Add the stats name
|
||||
// if it is a named stats and indent them as Go testing outputs.
|
||||
lines := strings.Split(stats.String(), "\n")
|
||||
if n := len(lines); n > 0 {
|
||||
if name != "" {
|
||||
name = ": " + name
|
||||
}
|
||||
fmt.Fprintf(orgStdout, "--- %s%s\n", lines[0], name)
|
||||
for _, line := range lines[1 : n-1] {
|
||||
fmt.Fprintf(orgStdout, "\t%s\n", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resetCurBenchStats()
|
||||
injectCond.Signal()
|
||||
}
|
||||
|
||||
// resetCurBenchStats resets the current benchmark stats.
|
||||
func resetCurBenchStats() {
|
||||
curB = nil
|
||||
curBenchName = ""
|
||||
curStats = make(map[string]*Stats)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue