Example #1
0
func TestEquals(t *testing.T) {
	h1 := hdrhistogram.New(1, 10000000, 3)
	for i := 0; i < 1000000; i++ {
		if err := h1.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	h2 := hdrhistogram.New(1, 10000000, 3)
	for i := 0; i < 10000; i++ {
		if err := h1.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	if h1.Equals(h2) {
		t.Error("Expected Histograms to not be equivalent")
	}

	h1.Reset()
	h2.Reset()

	if !h1.Equals(h2) {
		t.Error("Expected Histograms to be equivalent")
	}
}
Example #2
0
// Runf runs the given job at the given concurrency level, at the given rate,
// returning a set of results with aggregated latency and throughput
// measurements.
func (b Bench) Runf(concurrency int, rate float64, job Job) Result {
	var started, finished sync.WaitGroup
	started.Add(1)
	finished.Add(concurrency)

	result := Result{
		Concurrency: concurrency,
		Latency:     hdrhistogram.New(us(b.MinLatency), us(b.MaxLatency), 5),
	}
	timings := make(chan *hdrhistogram.Histogram, concurrency)
	errors := make(chan error, concurrency)

	workerRate := float64(concurrency) / rate
	period := time.Duration((workerRate)*1000000) * time.Microsecond

	for i := 0; i < concurrency; i++ {
		go func(id int) {
			defer finished.Done()

			gen := &Generator{
				hist:     hdrhistogram.New(us(b.MinLatency), us(b.MaxLatency), 5),
				success:  &result.Success,
				failure:  &result.Failure,
				period:   period,
				duration: b.Duration,
				warmup:   b.Warmup,
			}

			started.Wait()
			errors <- job(id, gen)
			timings <- gen.hist
		}(i)
	}

	started.Done()
	finished.Wait()
	result.Elapsed = b.Duration

	close(timings)
	for v := range timings {
		result.Latency.Merge(v)
	}

	close(errors)
	for e := range errors {
		if e != nil {
			result.Errors = append(result.Errors, e)
		}
	}

	return result
}
Example #3
0
func TestHighestTrackableValue(t *testing.T) {
	const maxVal = 11
	h := hdrhistogram.New(1, maxVal, 3)
	if h.HighestTrackableValue() != maxVal {
		t.Errorf("HighestTrackableValue figures was %v, expected %d", h.HighestTrackableValue(), maxVal)
	}
}
Example #4
0
func TestLowestTrackableValue(t *testing.T) {
	const minVal = 2
	h := hdrhistogram.New(minVal, 10, 3)
	if h.LowestTrackableValue() != minVal {
		t.Errorf("LowestTrackableValue figures was %v, expected %d", h.LowestTrackableValue(), minVal)
	}
}
Example #5
0
func TestByteSize(t *testing.T) {
	h := hdrhistogram.New(1, 100000, 3)

	if v, want := h.ByteSize(), 65604; v != want {
		t.Errorf("ByteSize was %v, but expected %d", v, want)
	}
}
Example #6
0
func TestCumulativeDistribution(t *testing.T) {
	h := hdrhistogram.New(1, 100000000, 3)

	for i := 0; i < 1000000; i++ {
		if err := h.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	actual := h.CumulativeDistribution()
	expected := []hdrhistogram.Bracket{
		hdrhistogram.Bracket{Quantile: 0, Count: 1, ValueAt: 0},
		hdrhistogram.Bracket{Quantile: 50, Count: 500224, ValueAt: 500223},
		hdrhistogram.Bracket{Quantile: 75, Count: 750080, ValueAt: 750079},
		hdrhistogram.Bracket{Quantile: 87.5, Count: 875008, ValueAt: 875007},
		hdrhistogram.Bracket{Quantile: 93.75, Count: 937984, ValueAt: 937983},
		hdrhistogram.Bracket{Quantile: 96.875, Count: 969216, ValueAt: 969215},
		hdrhistogram.Bracket{Quantile: 98.4375, Count: 984576, ValueAt: 984575},
		hdrhistogram.Bracket{Quantile: 99.21875, Count: 992256, ValueAt: 992255},
		hdrhistogram.Bracket{Quantile: 99.609375, Count: 996352, ValueAt: 996351},
		hdrhistogram.Bracket{Quantile: 99.8046875, Count: 998400, ValueAt: 998399},
		hdrhistogram.Bracket{Quantile: 99.90234375, Count: 999424, ValueAt: 999423},
		hdrhistogram.Bracket{Quantile: 99.951171875, Count: 999936, ValueAt: 999935},
		hdrhistogram.Bracket{Quantile: 99.9755859375, Count: 999936, ValueAt: 999935},
		hdrhistogram.Bracket{Quantile: 99.98779296875, Count: 999936, ValueAt: 999935},
		hdrhistogram.Bracket{Quantile: 99.993896484375, Count: 1000000, ValueAt: 1000447},
		hdrhistogram.Bracket{Quantile: 100, Count: 1000000, ValueAt: 1000447},
	}

	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("CF was %#v, but expected %#v", actual, expected)
	}
}
Example #7
0
func BenchmarkNew(b *testing.B) {
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		hdrhistogram.New(1, 120000, 3) // this could track 1ms-2min
	}
}
Example #8
0
func TestSignificantFigures(t *testing.T) {
	const sigFigs = 4
	h := hdrhistogram.New(1, 10, sigFigs)
	if h.SignificantFigures() != sigFigs {
		t.Errorf("Significant figures was %v, expected %d", h.SignificantFigures(), sigFigs)
	}
}
Example #9
0
File: bench.go Project: sbinq/bench
// aggregate run contexts
func (b *Bench) aggregate() {

	// aggregate timer metrics
	for _, n := range b.allContextsKeys(timerKeys) {
		t := hdrhistogram.New(min, max, precision)
		b.timers[n] = t
		for i := 0; i < b.concurrentRuns; i++ {
			otherTimer, ok := b.runContexts[i].timers[n]
			if ok {
				t.Merge(otherTimer)
			}
		}
	}

	// aggregate counters
	for _, n := range b.allContextsKeys(counterKeys) {
		for i := 0; i < b.concurrentRuns; i++ {
			b.counters[n] += b.runContexts[i].counters[n]
		}
	}

	// aggregate call counts
	for i := 0; i < b.concurrentRuns; i++ {
		b.calls += b.runContexts[i].Iteration
	}
}
Example #10
0
func TestValueAtQuantile(t *testing.T) {
	h := hdrhistogram.New(1, 10000000, 3)

	for i := 0; i < 1000000; i++ {
		if err := h.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	data := []struct {
		q float64
		v int64
	}{
		{q: 50, v: 500223},
		{q: 75, v: 750079},
		{q: 90, v: 900095},
		{q: 95, v: 950271},
		{q: 99, v: 990207},
		{q: 99.9, v: 999423},
		{q: 99.99, v: 999935},
	}

	for _, d := range data {
		if v := h.ValueAtQuantile(d.q); v != d.v {
			t.Errorf("P%v was %v, but expected %v", d.q, v, d.v)
		}
	}
}
Example #11
0
func TestExportImport(t *testing.T) {
	min := int64(1)
	max := int64(10000000)
	sigfigs := 3
	h := hdrhistogram.New(min, max, sigfigs)
	for i := 0; i < 1000000; i++ {
		if err := h.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	s := h.Export()

	if v := s.LowestTrackableValue; v != min {
		t.Errorf("LowestTrackableValue was %v, but expected %v", v, min)
	}

	if v := s.HighestTrackableValue; v != max {
		t.Errorf("HighestTrackableValue was %v, but expected %v", v, max)
	}

	if v := int(s.SignificantFigures); v != sigfigs {
		t.Errorf("SignificantFigures was %v, but expected %v", v, sigfigs)
	}

	if imported := hdrhistogram.Import(s); !imported.Equals(h) {
		t.Error("Expected Histograms to be equivalent")
	}

}
Example #12
0
// newConnectionBenchmark creates a connectionBenchmark which runs a system
// benchmark using the given Requester. The requestRate argument specifies the
// number of requests per second to issue. A zero value disables rate limiting
// entirely. The duration argument specifies how long to run the benchmark.
func newConnectionBenchmark(requester Requester, requestRate uint64, duration time.Duration) *connectionBenchmark {
	var interval time.Duration
	if requestRate > 0 {
		interval = time.Duration(1000000000 / requestRate)
	}

	return &connectionBenchmark{
		requester:                   requester,
		requestRate:                 requestRate,
		duration:                    duration,
		expectedInterval:            interval,
		successHistogram:            hdrhistogram.New(1, maxRecordableLatencyNS, sigFigs),
		uncorrectedSuccessHistogram: hdrhistogram.New(1, maxRecordableLatencyNS, sigFigs),
		errorHistogram:              hdrhistogram.New(1, maxRecordableLatencyNS, sigFigs),
		uncorrectedErrorHistogram:   hdrhistogram.New(1, maxRecordableLatencyNS, sigFigs),
	}
}
func TestNaN(t *testing.T) {
	h := hdrhistogram.New(1, 100000, 3)
	if math.IsNaN(h.Mean()) {
		t.Error("mean is NaN")
	}
	if math.IsNaN(h.StdDev()) {
		t.Error("stddev is NaN")
	}
}
Example #14
0
// NewHistogram initializes a given Histogram. The contained windowed histogram
// rotates every 'duration'; both the windowed and the cumulative histogram
// track nonnegative values up to 'maxVal' with 'sigFigs' decimal points of
// precision.
func NewHistogram(metadata Metadata, duration time.Duration, maxVal int64, sigFigs int) *Histogram {
	dHist := newSlidingHistogram(duration, maxVal, sigFigs)
	h := &Histogram{
		Metadata: metadata,
		maxVal:   maxVal,
	}
	h.mu.cumulative = hdrhistogram.New(0, maxVal, sigFigs)
	h.mu.sliding = dHist
	return h
}
Example #15
0
func TestRecordCorrectedValueStall(t *testing.T) {
	h := hdrhistogram.New(1, 100000, 3)

	if err := h.RecordCorrectedValue(1000, 100); err != nil {
		t.Fatal(err)
	}

	if v, want := h.ValueAtQuantile(75), int64(800); v != want {
		t.Errorf("Corrected value was %v, but expected %v", v, want)
	}
}
Example #16
0
func TestTotalCount(t *testing.T) {
	h := hdrhistogram.New(1, 10000000, 3)

	for i := 0; i < 1000000; i++ {
		if err := h.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
		if v, want := h.TotalCount(), int64(i+1); v != want {
			t.Errorf("TotalCount was %v, but expected %v", v, want)
		}
	}
}
Example #17
0
func TestMerge(t *testing.T) {
	h1 := hdrhistogram.New(1, 1000, 3)
	h2 := hdrhistogram.New(1, 1000, 3)

	for i := 0; i < 100; i++ {
		if err := h1.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	for i := 100; i < 200; i++ {
		if err := h2.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	h1.Merge(h2)

	if v, want := h1.ValueAtQuantile(50), int64(99); v != want {
		t.Errorf("Median was %v, but expected %v", v, want)
	}
}
Example #18
0
func NewHDRHistogram(low, high int64, sigfigs int) (h *HDRHistogram, err error) {
	defer func() {
		if msg := recover(); msg != nil {
			err = fmt.Errorf("%s", msg)
		}
	}()
	return &HDRHistogram{
		low:     low,
		high:    high,
		sigfigs: sigfigs,
		h:       hdrhistogram.New(low, high, sigfigs),
	}, nil
}
Example #19
0
func TestMax(t *testing.T) {
	h := hdrhistogram.New(1, 10000000, 3)

	for i := 0; i < 1000000; i++ {
		if err := h.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	if v, want := h.Max(), int64(999936); v != want {
		t.Errorf("Max was %v, but expected %v", v, want)
	}
}
Example #20
0
func TestStdDev(t *testing.T) {
	h := hdrhistogram.New(1, 10000000, 3)

	for i := 0; i < 1000000; i++ {
		if err := h.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	if v, want := h.StdDev(), 288675.1403682715; v != want {
		t.Errorf("StdDev was %v, but expected %v", v, want)
	}
}
Example #21
0
func BenchmarkHistogramRecordValue(b *testing.B) {
	h := hdrhistogram.New(1, 10000000, 3)
	for i := 0; i < 1000000; i++ {
		if err := h.RecordValue(int64(i)); err != nil {
			b.Fatal(err)
		}
	}
	b.ResetTimer()
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		h.RecordValue(100)
	}
}
Example #22
0
func TestHighSigFig(t *testing.T) {
	input := []int64{
		459876, 669187, 711612, 816326, 931423, 1033197, 1131895, 2477317,
		3964974, 12718782,
	}

	hist := hdrhistogram.New(459876, 12718782, 5)
	for _, sample := range input {
		hist.RecordValue(sample)
	}

	if v, want := hist.ValueAtQuantile(50), int64(1048575); v != want {
		t.Errorf("Median was %v, but expected %v", v, want)
	}
}
Example #23
0
func TestSubBucketMaskOverflow(t *testing.T) {
	hist := hdrhistogram.New(2e7, 1e8, 5)
	for _, sample := range [...]int64{1e8, 2e7, 3e7} {
		hist.RecordValue(sample)
	}

	for q, want := range map[float64]int64{
		50:    33554431,
		83.33: 33554431,
		83.34: 100663295,
		99:    100663295,
	} {
		if got := hist.ValueAtQuantile(q); got != want {
			t.Errorf("got %d for %fth percentile. want: %d", got, q, want)
		}
	}
}
Example #24
0
func (s *subscriber) start() {
	latencies := hdrhistogram.New(0, maxRecordableLatencyMS, sigFigs)
	for {
		message, err := s.Recv()
		now := time.Now().UnixNano()
		if err != nil {
			log.Printf("Subscriber error: %s", err.Error())
			s.mu.Lock()
			s.results = &result{Err: err.Error()}
			s.mu.Unlock()
			return
		}

		then, _ := binary.Varint(message)
		latencies.RecordValue((now - then) / 1000)

		if !s.hasStarted {
			s.hasStarted = true
			s.started = time.Now().UnixNano()
		}

		s.counter++
		if s.counter == s.numMessages {
			s.stopped = time.Now().UnixNano()
			durationMS := float32(s.stopped-s.started) / 1000000.0
			s.mu.Lock()
			s.results = &result{
				Duration:   durationMS,
				Throughput: 1000 * float32(s.numMessages) / durationMS,
				Latency: &latencyResults{
					Min:    latencies.Min(),
					Q1:     latencies.ValueAtQuantile(25),
					Q2:     latencies.ValueAtQuantile(50),
					Q3:     latencies.ValueAtQuantile(75),
					Max:    latencies.Max(),
					Mean:   latencies.Mean(),
					StdDev: latencies.StdDev(),
				},
			}
			s.mu.Unlock()
			log.Println("Subscriber completed")
			return
		}
	}
}
Example #25
0
func init() {
	stats.hist = hdrhistogram.New(0, 0x7fffffff, 1)
	stats.start = time.Now()
	stats.opCounts = map[int]int{}

	// Compute the total of all op relative frequencies.
	var relFreqTotal float64
	for _, op := range ops {
		relFreqTotal += op.relFreq
	}
	// Normalize frequencies.
	var normFreqTotal float64
	for _, op := range ops {
		normFreq := op.relFreq / relFreqTotal
		op.normFreq = normFreqTotal + normFreq
		normFreqTotal += normFreq
	}
}
Example #26
0
func TestDistribution(t *testing.T) {
	h := hdrhistogram.New(8, 1024, 3)

	for i := 0; i < 1024; i++ {
		if err := h.RecordValue(int64(i)); err != nil {
			t.Fatal(err)
		}
	}

	actual := h.Distribution()
	if len(actual) != 128 {
		t.Errorf("Number of bars seen was %v, expected was 128", len(actual))
	}
	for _, b := range actual {
		if b.Count != 8 {
			t.Errorf("Count per bar seen was %v, expected was 8", b.Count)
		}
	}
}
Example #27
0
func NewOneMeasurementHdrHistogram(name string, props Properties) (*OneMeasurementHdrHistogram, error) {
	prop := props.GetDefault(PropertyPercentiles, PropertyPercentilesDefault)
	percentiles := parsePercentileValues(prop, PropertyPercentilesDefault)
	prop = props.GetDefault(PropertyHdrHistogramOutput, PropertyHdrHistogramOutputDefault)
	shouldLog, err := strconv.ParseBool(prop)
	if err != nil {
		return nil, err
	}
	prop = props.GetDefault(PropertyHdrHistogramMax, PropertyHdrHistogramMaxDefault)
	max, err := strconv.ParseInt(prop, 0, 64)
	if err != nil {
		return nil, err
	}
	prop = props.GetDefault(PropertyHdrHistogramSig, PropertyHdrHistogramSigDefault)
	sig, err := strconv.ParseInt(prop, 0, 64)
	if err != nil {
		return nil, err
	}
	var filePath string
	var f *os.File
	var writer *HdrHistogramLogWriter
	if !shouldLog {
		filePath = ""
		f = nil
		writer = nil
	} else {
		filePath = props.GetDefault(PropertyHdrHistogramOutputPath, PropertyHdrHistogramOutputPathDefault)
		f, err = os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			return nil, err
		}
		writer = NewHdrHistogramLogWriter(f)
	}
	object := &OneMeasurementHdrHistogram{
		OneMeasurementBase: NewOneMeasurementBase(name),
		histogram:          hdrhistogram.New(0, max, int(sig)),
		filePath:           filePath,
		file:               f,
		writer:             writer,
		percentiles:        percentiles,
	}
	return object, nil
}
Example #28
0
func (s *Sampler) Init() {
	s.outOfRangeErrors = 0
	s.histogram = hdrhistogram.New(s.Min, s.Max, s.Sigint)

	// we need to know the bucket Quantiles, for this we just add every possible value to the histogram..
	for i := s.Min; i < s.Max; i++ {
		s.histogram.RecordValue(i)
	}

	//We then extract hdrhistograms own bucket range
	distribution := s.histogram.CumulativeDistribution()
	s.bucketQuantiles = make([]float64, 0, len(distribution))

	//and save it for later use
	for _, d := range distribution {
		s.bucketQuantiles = append(s.bucketQuantiles, d.Quantile)
	}

	s.histogram.Reset()

	// Pipe stuff
	// Check if pipe already exists
	pipeExists := false
	fileInfo, err := os.Stat(s.Path)

	if err == nil {
		if (fileInfo.Mode() & os.ModeNamedPipe) > 0 {
			pipeExists = true
		} else {
			fmt.Printf("%d != %d\n", os.ModeNamedPipe, fileInfo.Mode())
			panic(s.Path + " exists, but it's not a named pipe (FIFO)")
		}
	}

	// Try to create pipe if needed
	if !pipeExists {
		err := syscall.Mkfifo(s.Path, 0666)
		if err != nil {
			panic(err.Error())
		}
	}

}
Example #29
0
// AssertCirconusNormalHistogram ensures the Circonus Histogram data captured in
// the result slice abides a normal distribution.
func AssertCirconusNormalHistogram(t *testing.T, mean, stdev, min, max int64, result []string) {
	if len(result) <= 0 {
		t.Fatal("no results")
	}

	// Circonus just dumps the raw counts. We need to do our own statistical analysis.
	h := hdrhistogram.New(min, max, 3)

	for _, s := range result {
		// "H[1.23e04]=123"
		toks := strings.Split(s, "=")
		if len(toks) != 2 {
			t.Fatalf("bad H value: %q", s)
		}

		var bucket string
		bucket = toks[0]
		bucket = bucket[2 : len(bucket)-1] // "H[1.23e04]" -> "1.23e04"
		f, err := strconv.ParseFloat(bucket, 64)
		if err != nil {
			t.Fatalf("error parsing H value: %q: %v", s, err)
		}

		count, err := strconv.ParseFloat(toks[1], 64)
		if err != nil {
			t.Fatalf("error parsing H count: %q: %v", s, err)
		}

		h.RecordValues(int64(f), int64(count))
	}

	// Apparently Circonus buckets observations by dropping a sigfig, so we have
	// very coarse tolerance.
	var tolerance int64 = 30
	for _, quantile := range []int{50, 90, 99} {
		want := normalValueAtQuantile(mean, stdev, quantile)
		have := h.ValueAtQuantile(float64(quantile))
		if int64(math.Abs(float64(want)-float64(have))) > tolerance {
			t.Errorf("quantile %d: want %d, have %d", quantile, want, have)
		}
	}
}
Example #30
0
// aggregate run contexts
func (b *Bench) aggregate() {

	// aggregate timer metrics
	for n := range b.runContexts[0].timers {
		t := hdrhistogram.New(min, max, precision)
		b.timers[n] = t
		for i := 0; i < b.concurrentRuns; i++ {
			t.Merge(b.runContexts[i].timers[n])
		}
	}

	// aggregate counters
	for n := range b.runContexts[0].counters {
		for i := 0; i < b.concurrentRuns; i++ {
			b.counters[n] += b.runContexts[i].counters[n]
		}
	}

	// aggregate call counts
	for i := 0; i < b.concurrentRuns; i++ {
		b.calls += b.runContexts[i].Iteration
	}
}