From 76b46e1cc745c5b8346f4301755862172e61bbcd Mon Sep 17 00:00:00 2001 From: Brian Dillmann Date: Mon, 17 Aug 2026 11:15:02 -0400 Subject: [PATCH 1/3] goodhistogram: perf-eval of exact min/max tracking on the hot path Add experimental RecordMinMax / RecordMinMaxPadded variants that track the exact minimum and maximum observed value via a load-guarded CAS loop, plus an A/B benchmark across input ordering (steady/ascending/descending) and concurrency (1/50/100 goroutines). Includes arm64 (Apple M3 Pro) results and write-up under reports/. Co-Authored-By: roachdev-claude --- histogram.go | 27 ++++- minmax.go | 74 ++++++++++++ minmax_benchmark_test.go | 122 +++++++++++++++++++ reports/minmax_benchstat.txt | 42 +++++++ reports/minmax_perf_eval.md | 104 ++++++++++++++++ reports/minmax_raw.txt | 222 +++++++++++++++++++++++++++++++++++ 6 files changed, 590 insertions(+), 1 deletion(-) create mode 100644 minmax.go create mode 100644 minmax_benchmark_test.go create mode 100644 reports/minmax_benchstat.txt create mode 100644 reports/minmax_perf_eval.md create mode 100644 reports/minmax_raw.txt diff --git a/histogram.go b/histogram.go index 3a11051..36b6490 100644 --- a/histogram.go +++ b/histogram.go @@ -307,6 +307,26 @@ type Histogram struct { // ZeroCount counts exact zeros (and negative values). ZeroCount atomic.Uint64 sum atomic.Int64 // using Int64 since CockroachDB histograms record int64 + + // min/max track the exact smallest and largest values recorded, for + // the perf-eval of exact extreme tracking. Updated only by the + // RecordMinMax* variants. min is seeded to MaxInt64 and max to + // MinInt64 so the first observation always wins. + min atomic.Int64 + max atomic.Int64 + + // minP/maxP are cache-line-padded variants of min/max, used by + // RecordMinMaxPadded to isolate the false-sharing cost of placing the + // extremes next to the hot sum counter on the same cache line. + minP paddedInt64 + maxP paddedInt64 +} + +// paddedInt64 is an atomic.Int64 padded to a full 64-byte cache line so +// that updates to it do not invalidate neighbouring fields (false sharing). +type paddedInt64 struct { + v atomic.Int64 + _ [56]byte // 64 - 8 bytes } // Reset zeroes all counters without reallocating the backing slice. @@ -325,10 +345,15 @@ func (h *Histogram) Reset() { func New(p Params) *Histogram { p = p.withDefaults() cfg := getOrCreateConfig(p) - return &Histogram{ + h := &Histogram{ cfg: cfg, counts: make([]atomic.Uint64, cfg.numBuckets), } + h.min.Store(math.MaxInt64) + h.max.Store(math.MinInt64) + h.minP.v.Store(math.MaxInt64) + h.maxP.v.Store(math.MinInt64) + return h } // Record adds a value to the histogram. This is the hot path: O(1), lock-free, diff --git a/minmax.go b/minmax.go new file mode 100644 index 0000000..a50913d --- /dev/null +++ b/minmax.go @@ -0,0 +1,74 @@ +// Copyright 2026 The Cockroach 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 + +package goodhistogram + +import "sync/atomic" + +// This file holds experimental variants of Record that additionally track the +// exact minimum and maximum values observed. They exist purely for the +// performance evaluation of exact extreme tracking on the lock-free hot path +// and are compared A/B against the baseline Record in minmax_benchmark_test.go. +// +// Tracking exact extremes cannot use a fetch-and-add like the bucket counters +// and sum; it needs a compare-and-swap loop guarded by a relaxed load. The +// load short-circuits the common steady-state case (the value is not a new +// extreme), so the CAS only fires when a new extreme is actually seen. The +// interesting cost is therefore (a) two extra shared-atomic loads on every +// Record and (b) contended CAS retries when extremes churn. + +// updateMin lowers dst toward v using a load-guarded CAS loop. +func updateMin(dst *atomic.Int64, v int64) { + for { + old := dst.Load() + if v >= old { + return + } + if dst.CompareAndSwap(old, v) { + return + } + } +} + +// updateMax raises dst toward v using a load-guarded CAS loop. +func updateMax(dst *atomic.Int64, v int64) { + for { + old := dst.Load() + if v <= old { + return + } + if dst.CompareAndSwap(old, v) { + return + } + } +} + +// RecordMinMax records v and additionally tracks the exact min and max in two +// atomics packed inline in the Histogram struct (adjacent to sum, so they may +// share a cache line with the other hot counters). +func (h *Histogram) RecordMinMax(v int64) { + updateMin(&h.min, v) + updateMax(&h.max, v) + h.Record(v) +} + +// RecordMinMaxPadded records v and tracks exact min and max in cache-line +// padded atomics, isolating the false-sharing cost from the inline variant. +func (h *Histogram) RecordMinMaxPadded(v int64) { + updateMin(&h.minP.v, v) + updateMax(&h.maxP.v, v) + h.Record(v) +} + +// Min returns the exact minimum recorded via a RecordMinMax variant, or +// MaxInt64 if none. +func (h *Histogram) Min() int64 { return h.min.Load() } + +// Max returns the exact maximum recorded via a RecordMinMax variant, or +// MinInt64 if none. +func (h *Histogram) Max() int64 { return h.max.Load() } diff --git a/minmax_benchmark_test.go b/minmax_benchmark_test.go new file mode 100644 index 0000000..3b8cadf --- /dev/null +++ b/minmax_benchmark_test.go @@ -0,0 +1,122 @@ +// Copyright 2026 The Cockroach 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 + +package goodhistogram + +import ( + "fmt" + "math/rand" + "sort" + "testing" +) + +// -------------------------------------------------------------------------- +// Performance evaluation: exact min/max tracking on the hot Record path. +// +// Baseline is the existing Record. The variants add a load-guarded CAS loop +// for both the exact min and the exact max: +// +// record - baseline, no extreme tracking +// record-minmax - min/max in atomics packed inline next to sum +// record-padded - min/max in cache-line-padded atomics (no false sharing) +// +// The cost of extreme tracking depends entirely on how often a new extreme is +// seen, which is a property of input *ordering*, not the distribution's shape: +// +// steady - shuffled log-uniform values. After a brief warm-up the extremes +// stop moving, so every CAS is skipped by the guard load. This is +// the common metrics case (latencies bounce around a stable range). +// ascending- monotonically increasing values: every single Record sets a new +// max, forcing a CAS on every call. Adversarial worst case. +// descending- monotonically decreasing: every Record sets a new min. +// -------------------------------------------------------------------------- + +type ordering struct { + name string + gen func(rng *rand.Rand, n int) []int64 +} + +var minMaxOrderings = []ordering{ + { + name: "steady", + gen: func(rng *rand.Rand, n int) []int64 { + return makeInt64Values(rng, n) // shuffled log-uniform + }, + }, + { + name: "ascending", + gen: func(rng *rand.Rand, n int) []int64 { + v := makeInt64Values(rng, n) + sort.Slice(v, func(i, j int) bool { return v[i] < v[j] }) + return v + }, + }, + { + name: "descending", + gen: func(rng *rand.Rand, n int) []int64 { + v := makeInt64Values(rng, n) + sort.Slice(v, func(i, j int) bool { return v[i] > v[j] }) + return v + }, + }, +} + +// recordVariants maps a name to the record method under test. +var recordVariants = []struct { + name string + fn func(h *Histogram, v int64) +}{ + {"record", (*Histogram).Record}, + {"record-minmax", (*Histogram).RecordMinMax}, + {"record-padded", (*Histogram).RecordMinMaxPadded}, +} + +// BenchmarkMinMaxSingleThread measures per-Record cost single-threaded, across +// input orderings. Isolates the raw instruction/CAS cost with no contention. +func BenchmarkMinMaxSingleThread(b *testing.B) { + const nVals = 100_000 + for _, ord := range minMaxOrderings { + vals := ord.gen(rand.New(rand.NewSource(42)), nVals) + for _, variant := range recordVariants { + b.Run(fmt.Sprintf("order=%s/%s", ord.name, variant.name), func(b *testing.B) { + h := newGoodHist() + b.ResetTimer() + for i := 0; i < b.N; i++ { + variant.fn(h, vals[i%len(vals)]) + } + }) + } + } +} + +// BenchmarkMinMaxContention measures per-Record cost under contention. This is +// where extreme tracking is expected to hurt most: the shared min/max atomics +// bounce between cores' caches even when the guard load skips the CAS, and +// under the ascending/descending orderings the CAS itself is heavily contended. +func BenchmarkMinMaxContention(b *testing.B) { + const nVals = 100_000 + for _, numG := range []int{50, 100} { + for _, ord := range minMaxOrderings { + vals := ord.gen(rand.New(rand.NewSource(42)), nVals) + for _, variant := range recordVariants { + b.Run(fmt.Sprintf("g=%d/order=%s/%s", numG, ord.name, variant.name), func(b *testing.B) { + h := newGoodHist() + b.SetParallelism(numG) + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + i := 0 + for pb.Next() { + variant.fn(h, vals[i%len(vals)]) + i++ + } + }) + }) + } + } + } +} diff --git a/reports/minmax_benchstat.txt b/reports/minmax_benchstat.txt new file mode 100644 index 0000000..acb1eb9 --- /dev/null +++ b/reports/minmax_benchstat.txt @@ -0,0 +1,42 @@ +Single-threaded (sec/op, vs baseline): + │ SingleThread_baseline.txt │ SingleThread_minmax.txt │ SingleThread_padded.txt │ + │ sec/op │ sec/op vs base │ sec/op vs base │ +MinMaxSingleThread/order=steady-11 2.751n ± 1% 3.456n ± 1% +25.63% (p=0.000 n=8) 3.446n ± 7% +25.25% (p=0.000 n=8) +MinMaxSingleThread/order=ascending-11 2.690n ± 5% 3.488n ± 1% +29.65% (p=0.000 n=8) 4.941n ± 30% +83.70% (p=0.000 n=8) +MinMaxSingleThread/order=descending-11 3.827n ± 30% 3.504n ± 1% ~ (p=0.105 n=8) 4.610n ± 25% +20.46% (p=0.005 n=8) + │ SingleThread_baseline.txt │ SingleThread_minmax.txt │ SingleThread_padded.txt │ + │ B/op │ B/op vs base │ B/op vs base │ +MinMaxSingleThread/order=steady-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=ascending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=descending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ + │ SingleThread_baseline.txt │ SingleThread_minmax.txt │ SingleThread_padded.txt │ + │ allocs/op │ allocs/op vs base │ allocs/op vs base │ +MinMaxSingleThread/order=steady-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=ascending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=descending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ + +Contention (sec/op, vs baseline): + │ Contention_baseline.txt │ Contention_minmax.txt │ Contention_padded.txt │ + │ sec/op │ sec/op vs base │ sec/op vs base │ +MinMaxContention/g=50/order=steady-11 43.44n ± 13% 51.82n ± 27% +19.29% (p=0.007 n=8) 54.88n ± 13% +26.35% (p=0.000 n=8) +MinMaxContention/g=50/order=ascending-11 51.12n ± 4% 49.65n ± 12% ~ (p=0.645 n=8) 57.22n ± 18% +11.93% (p=0.010 n=8) +MinMaxContention/g=50/order=descending-11 38.88n ± 27% 36.49n ± 15% ~ (p=0.645 n=8) 60.43n ± 10% +55.43% (p=0.000 n=8) +MinMaxContention/g=100/order=steady-11 54.62n ± 6% 52.15n ± 26% ~ (p=0.645 n=8) 55.14n ± 20% ~ (p=0.442 n=8) +MinMaxContention/g=100/order=ascending-11 55.24n ± 8% 53.03n ± 6% ~ (p=0.342 n=8) 60.41n ± 23% ~ (p=0.130 n=8) +MinMaxContention/g=100/order=descending-11 41.14n ± 19% 37.01n ± 11% ~ (p=0.442 n=8) 63.93n ± 29% +55.38% (p=0.001 n=8) + │ Contention_baseline.txt │ Contention_minmax.txt │ Contention_padded.txt │ + │ B/op │ B/op vs base │ B/op vs base │ +MinMaxContention/g=50/order=steady-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=ascending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=descending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=steady-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=ascending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=descending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ + │ Contention_baseline.txt │ Contention_minmax.txt │ Contention_padded.txt │ + │ allocs/op │ allocs/op vs base │ allocs/op vs base │ +MinMaxContention/g=50/order=steady-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=ascending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=descending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=steady-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=ascending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=descending-11 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ diff --git a/reports/minmax_perf_eval.md b/reports/minmax_perf_eval.md new file mode 100644 index 0000000..3955c87 --- /dev/null +++ b/reports/minmax_perf_eval.md @@ -0,0 +1,104 @@ +# Performance evaluation: exact min/max tracking on the hot path + +**Question:** what does it cost to track the *exact* minimum and maximum value a +`goodhistogram` has seen, added to the lock-free `Record` hot path? + +Today `Record` does a `sum.Add` and a single `counts[idx].Add` — both +fetch-and-add. Exact extremes can't use fetch-and-add; each needs a +compare-and-swap loop guarded by a relaxed load: + +```go +for { + old := dst.Load() + if v >= old { return } // guard: skip CAS unless v is a new extreme + if dst.CompareAndSwap(old, v) { return } +} +``` + +The guard load short-circuits the steady state (`v` isn't a new extreme), so the +CAS only fires when an extreme actually moves. The costs to measure are therefore +(a) two extra shared-atomic **loads** on every `Record`, and (b) contended CAS +retries when extremes churn. + +## What was measured + +Three `Record` variants, A/B benchmarked (`minmax.go`, `minmax_benchmark_test.go`): + +| variant | description | +|------------|-------------| +| `baseline` | existing `Record`, no extreme tracking | +| `minmax` | min/max in two `atomic.Int64` packed **inline** in the struct (adjacent to `sum`) | +| `padded` | min/max in **cache-line-padded** atomics (each on its own 64-byte line), to isolate false sharing | + +Cost depends on input **ordering**, not distribution shape, so orderings are the +independent variable: + +- **steady** — shuffled log-uniform. Extremes settle after warm-up, then every CAS + is skipped by the guard. This is the normal metrics case. +- **ascending** — monotonically increasing: every `Record` sets a new max → CAS + every call. Adversarial worst case. +- **descending** — monotonically decreasing: every `Record` sets a new min. + +Machine: Apple M3 Pro (arm64), schema 2, range [500, 6e10], `-count=8`. +Raw data: `minmax_raw.txt`; benchstat: `minmax_benchstat.txt`. + +## Results + +### Single-threaded (sec/op, vs. baseline) + +| ordering | baseline | minmax | padded | +|------------|----------|-----------------|-----------------| +| steady | 2.75n | 3.46n (+25.6%) | 3.45n (+25.3%) | +| ascending | 2.69n | 3.49n (+29.7%) | 4.94n (+83.7%, ±30%) | +| descending | 3.83n ±30% | 3.50n (~, n.s.) | 4.61n (+20.5%) | + +### High contention (sec/op, vs. baseline) + +| ordering | baseline | minmax | padded | +|---------------------|----------|-----------------|-----------------| +| g=50, steady | 43.4n | 51.8n (+19.3%) | 54.9n (+26.4%) | +| g=50, ascending | 51.1n | 49.7n (~, n.s.) | 57.2n (+11.9%) | +| g=50, descending | 38.9n | 36.5n (~, n.s.) | 60.4n (+55.4%) | +| g=100, steady | 54.6n | 52.2n (~, n.s.) | 55.1n (~, n.s.) | +| g=100, ascending | 55.2n | 53.0n (~, n.s.) | 60.4n (~, n.s.) | +| g=100, descending | 41.1n | 37.0n (~, n.s.) | 63.9n (+55.4%) | + +("~, n.s." = not statistically significant, p > 0.05.) + +## Findings + +1. **Single-threaded overhead is small in absolute terms: ~0.7–0.8 ns/op** + (+25–30% on a ~2.7 ns baseline). Even the adversarial ascending case + (CAS on *every* call) costs only ~0.8 ns more — an uncontended CAS is nearly + as cheap as the guard load, so worst-case ≈ steady-state single-threaded. + +2. **Under contention, inline min/max is effectively free.** In 5 of 6 cases the + inline `minmax` variant is statistically indistinguishable from baseline + (often nominally faster, within noise). The contended `sum.Add` already + dominates the hot path; two read-mostly guard loads that land on an + already-bounced cache line add nothing measurable. Contention runs are noisy + (baseline itself ±10–30%), so treat these as "no detectable regression" + rather than precise deltas. + +3. **Cache-line padding is a pessimization here — the counterintuitive result.** + The `padded` variant is consistently *worse* than inline under contention + (up to +55%). Padding is the standard fix for false sharing, but the extremes + are **read-mostly**: in the inline layout their guard loads piggyback on the + `sum` cache line the core already owns each iteration (it just did `sum.Add`). + Padding moves them onto two *separate* lines that must be fetched + additionally, tripling the hot coherence footprint (1 line → 3). Co-locating + the extremes with the already-hot `sum` is the right call; do **not** pad. + +## Recommendation + +Exact min/max tracking is cheap enough to add: **~0.8 ns/op single-threaded and +no detectable regression under contention**, zero extra allocations. Use the +**inline** layout (`minmax` variant) and keep the load-guarded CAS. Avoid +cache-line padding. + +If the ~0.8 ns single-threaded cost ever matters on an ultra-hot path, the guard +load is what makes it cheap — no cheaper exact scheme exists (exact extremes +fundamentally require CAS, not fetch-and-add). An approximate alternative would +be to derive min/max from the populated bucket edges at `Snapshot` time for +**zero** hot-path cost, at the price of bucket-width error (≤ the configured +relative error bound) instead of exact values. diff --git a/reports/minmax_raw.txt b/reports/minmax_raw.txt new file mode 100644 index 0000000..49089f6 --- /dev/null +++ b/reports/minmax_raw.txt @@ -0,0 +1,222 @@ +goos: darwin +goarch: arm64 +pkg: github.com/cockroachdb/goodhistogram +cpu: Apple M3 Pro +BenchmarkMinMaxSingleThread/order=steady/record-11 436528590 2.774 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-11 433542782 2.765 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-11 426445167 2.742 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-11 442759701 2.742 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-11 433949691 2.756 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-11 441503200 2.808 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-11 423816111 2.743 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-11 435924606 2.746 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-11 353757984 3.407 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-11 347231138 3.445 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-11 356552272 3.435 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-11 339466197 3.422 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-11 347367042 3.467 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-11 355728588 3.482 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-11 259282376 4.053 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-11 327183049 3.501 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-11 342347412 3.422 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-11 352365343 3.696 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-11 350025412 3.424 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-11 338669295 3.379 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-11 352043894 3.451 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-11 321886360 3.490 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-11 330836740 3.440 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-11 354012628 3.911 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-11 445500651 2.682 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-11 440147637 2.821 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-11 443136848 2.692 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-11 445647002 2.688 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-11 436502126 2.773 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-11 449570028 2.685 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-11 447644271 2.676 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-11 453721365 2.888 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-11 299895723 3.534 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-11 337894081 3.493 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-11 350095704 3.469 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-11 340989050 3.457 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-11 350129966 3.482 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-11 340875519 3.467 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-11 329281869 3.547 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-11 346931982 3.495 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-11 349937247 3.448 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-11 342356079 3.876 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-11 270344071 4.752 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-11 291666523 5.005 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-11 287757333 5.277 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-11 301918725 5.594 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-11 303874206 5.245 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-11 304466865 4.878 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-11 409983321 3.939 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-11 345312340 3.714 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-11 332173051 4.509 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-11 376977609 3.698 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-11 387625329 4.213 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-11 387091778 4.051 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-11 425795394 2.701 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-11 444242272 2.682 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-11 307779577 3.644 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-11 340992441 3.496 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-11 345177267 3.475 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-11 347246293 3.538 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-11 345701026 3.533 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-11 342334755 3.465 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-11 341309020 3.511 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-11 348077097 3.456 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-11 342584787 3.471 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-11 347059454 4.617 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-11 284303653 4.511 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-11 308535802 4.602 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-11 262647462 6.183 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-11 291887095 5.697 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-11 235557445 4.525 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-11 282057802 4.966 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-11 28482622 44.79 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-11 22988174 44.72 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-11 27217209 38.60 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-11 27598107 43.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-11 24184060 43.45 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-11 33548842 37.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-11 32062129 42.23 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-11 30123927 44.24 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-11 33676405 46.28 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-11 32323279 38.08 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-11 19846356 50.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-11 23282660 63.38 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-11 27896650 51.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-11 23740885 51.78 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-11 23501582 51.92 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-11 22647514 51.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-11 18514291 54.73 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-11 21077899 64.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-11 22140476 55.01 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-11 21440790 54.76 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-11 22381065 61.90 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-11 29835222 52.23 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-11 21997023 55.42 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-11 21918788 52.57 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-11 21519468 52.28 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-11 20480727 52.31 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-11 20732863 48.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-11 23641540 50.13 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-11 20135269 50.01 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-11 20548618 52.76 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-11 20775802 52.09 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-11 26041269 50.14 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-11 22430516 47.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-11 22955170 43.59 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-11 24744819 44.60 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-11 24078271 51.32 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-11 25034059 54.03 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-11 24253443 52.73 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-11 26649811 47.61 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-11 33036536 58.53 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-11 18270054 57.22 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-11 20926412 57.21 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-11 20269982 55.21 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-11 17553418 59.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-11 17470172 61.06 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-11 18500733 58.96 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-11 22251301 46.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-11 18880082 56.77 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-11 25474393 48.92 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-11 23100523 50.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-11 24087618 46.81 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-11 98139102 28.55 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-11 35625196 37.85 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-11 39733263 36.70 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-11 25718418 39.91 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-11 35518056 32.31 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-11 30751108 36.38 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-11 34690920 31.36 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-11 38095566 33.79 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-11 34619671 36.59 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-11 33618049 41.23 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-11 40487971 36.21 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-11 31402294 41.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-11 27444537 60.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-11 40229250 54.16 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-11 19860492 62.23 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-11 20199525 60.40 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-11 20749712 63.68 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-11 19354096 58.09 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-11 16986019 59.89 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-11 16970145 66.52 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-11 21919492 60.46 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-11 22555207 56.76 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-11 22763306 51.22 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-11 21252588 52.55 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-11 23475861 58.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-11 23349406 52.51 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-11 20268885 52.34 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-11 22910035 56.69 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-11 22953199 57.40 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-11 22199644 65.77 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-11 24135601 50.62 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-11 23125876 52.48 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-11 22755991 51.82 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-11 23081296 49.85 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-11 22644481 48.09 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-11 23038418 65.08 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-11 22462952 65.61 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-11 22148632 54.48 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-11 22721796 54.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-11 21687066 66.21 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-11 20046970 53.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-11 21401020 54.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-11 22551189 55.41 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-11 18104667 55.93 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-11 21839541 66.48 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-11 21346899 51.39 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-11 22717519 54.31 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-11 21265785 59.54 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-11 25560964 56.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-11 27081871 51.81 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-11 20116170 56.17 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-11 19616590 58.58 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-11 35007918 50.63 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-11 24220977 57.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-11 28202518 50.60 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-11 23214746 51.32 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-11 21826540 56.17 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-11 20894660 53.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-11 20358627 56.13 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-11 21897512 51.34 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-11 22869640 52.13 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-11 26931757 51.76 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-11 41623249 56.40 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-11 21241663 60.04 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-11 17446033 61.57 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-11 18439150 62.81 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-11 21439482 46.67 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-11 20566506 63.34 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-11 17693307 60.78 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-11 23835435 49.15 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-11 20992921 48.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-11 34960832 45.42 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-11 25232546 52.42 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-11 98548794 36.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-11 39520406 36.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-11 36336297 34.96 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-11 41697181 33.90 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-11 36834213 35.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-11 40419678 36.78 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-11 35762732 41.22 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-11 35004296 42.32 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-11 39146953 33.51 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-11 33612414 39.15 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-11 29431605 36.81 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-11 30273306 37.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-11 34091323 45.45 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-11 18710580 57.91 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-11 22605084 70.75 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-11 18401850 66.02 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-11 22052343 56.17 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-11 22317710 62.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-11 19007166 64.91 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-11 16773968 65.19 ns/op 0 B/op 0 allocs/op +PASS +ok github.com/cockroachdb/goodhistogram 379.416s From df8fc2228775384963bec9b0ad914d1655572a21 Mon Sep 17 00:00:00 2001 From: Brian Dillmann Date: Mon, 17 Aug 2026 11:36:26 -0400 Subject: [PATCH 2/3] goodhistogram: add x86 (GCE worker) results to min/max perf-eval Run the same A/B suite on gceworker-briandillmann (24 vCPU x86_64, Go 1.25.5) and add a cross-architecture comparison. x86 shows a clean, consistent ~10% Record overhead for inline min/max (arm64 M3 numbers were noisy under contention). Padding is neutral-to-worse on both arches. Co-Authored-By: roachdev-claude --- reports/minmax_benchstat_amd64.txt | 33 +++ ...nchstat.txt => minmax_benchstat_arm64.txt} | 0 reports/minmax_perf_eval.md | 107 ++++++--- reports/minmax_raw_amd64.txt | 226 ++++++++++++++++++ .../{minmax_raw.txt => minmax_raw_arm64.txt} | 0 5 files changed, 330 insertions(+), 36 deletions(-) create mode 100644 reports/minmax_benchstat_amd64.txt rename reports/{minmax_benchstat.txt => minmax_benchstat_arm64.txt} (100%) create mode 100644 reports/minmax_raw_amd64.txt rename reports/{minmax_raw.txt => minmax_raw_arm64.txt} (100%) diff --git a/reports/minmax_benchstat_amd64.txt b/reports/minmax_benchstat_amd64.txt new file mode 100644 index 0000000..8fa39e3 --- /dev/null +++ b/reports/minmax_benchstat_amd64.txt @@ -0,0 +1,33 @@ +x86_64 GCE worker (24 vCPU), Go 1.25.5 +Single-threaded (sec/op, vs baseline): + │ sec/op │ sec/op vs base │ sec/op vs base │ +MinMaxSingleThread/order=steady-24 20.86n ± 0% 23.00n ± 0% +10.31% (p=0.000 n=8) 22.71n ± 0% +8.92% (p=0.000 n=8) +MinMaxSingleThread/order=ascending-24 20.86n ± 0% 22.98n ± 0% +10.16% (p=0.000 n=8) 22.68n ± 0% +8.70% (p=0.000 n=8) +MinMaxSingleThread/order=descending-24 20.88n ± 0% 23.02n ± 0% +10.28% (p=0.000 n=8) 22.67n ± 0% +8.57% (p=0.000 n=8) +MinMaxSingleThread/order=steady-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=ascending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=descending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=steady-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=ascending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=descending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ + +Contention (sec/op, vs baseline): + │ sec/op │ sec/op vs base │ sec/op vs base │ +MinMaxContention/g=50/order=steady-24 39.70n ± 2% 43.83n ± 1% +10.39% (p=0.000 n=8) 44.18n ± 4% +11.28% (p=0.000 n=8) +MinMaxContention/g=50/order=ascending-24 39.00n ± 42% 43.16n ± 1% +10.67% (p=0.000 n=8) 43.38n ± 7% +11.23% (p=0.000 n=8) +MinMaxContention/g=50/order=descending-24 38.91n ± 42% 42.97n ± 1% +10.45% (p=0.000 n=8) 43.22n ± 6% +11.08% (p=0.000 n=8) +MinMaxContention/g=100/order=steady-24 39.57n ± 1% 43.68n ± 1% +10.40% (p=0.000 n=8) 42.93n ± 7% +8.50% (p=0.000 n=8) +MinMaxContention/g=100/order=ascending-24 39.29n ± 2% 42.75n ± 2% +8.81% (p=0.000 n=8) 44.46n ± 10% +13.17% (p=0.000 n=8) +MinMaxContention/g=100/order=descending-24 38.27n ± 40% 42.78n ± 2% +11.77% (p=0.000 n=8) 44.74n ± 11% +16.90% (p=0.000 n=8) +MinMaxContention/g=50/order=steady-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=ascending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=descending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=steady-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=ascending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=descending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=steady-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=ascending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=descending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=steady-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=ascending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=descending-24 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ diff --git a/reports/minmax_benchstat.txt b/reports/minmax_benchstat_arm64.txt similarity index 100% rename from reports/minmax_benchstat.txt rename to reports/minmax_benchstat_arm64.txt diff --git a/reports/minmax_perf_eval.md b/reports/minmax_perf_eval.md index 3955c87..91a8b86 100644 --- a/reports/minmax_perf_eval.md +++ b/reports/minmax_perf_eval.md @@ -39,10 +39,12 @@ independent variable: every call. Adversarial worst case. - **descending** — monotonically decreasing: every `Record` sets a new min. -Machine: Apple M3 Pro (arm64), schema 2, range [500, 6e10], `-count=8`. -Raw data: `minmax_raw.txt`; benchstat: `minmax_benchstat.txt`. +Run on two machines, schema 2, range [500, 6e10], `-count=8`: +- **arm64** — Apple M3 Pro (laptop). Raw: `minmax_raw_arm64.txt`; benchstat: `minmax_benchstat_arm64.txt`. +- **amd64** — GCE worker `gceworker-briandillmann`, 24 vCPU x86_64, Go 1.25.5. + Raw: `minmax_raw_amd64.txt`; benchstat: `minmax_benchstat_amd64.txt`. -## Results +## Results — arm64 (Apple M3 Pro) ### Single-threaded (sec/op, vs. baseline) @@ -63,42 +65,75 @@ Raw data: `minmax_raw.txt`; benchstat: `minmax_benchstat.txt`. | g=100, ascending | 55.2n | 53.0n (~, n.s.) | 60.4n (~, n.s.) | | g=100, descending | 41.1n | 37.0n (~, n.s.) | 63.9n (+55.4%) | -("~, n.s." = not statistically significant, p > 0.05.) +("~, n.s." = not statistically significant, p > 0.05.) The M3's contention +numbers are noisy (baseline ±10–40%), which is why several deltas land as n.s. + +## Results — amd64 (GCE worker, 24 vCPU x86_64) + +Far lower variance (±0–2%), so every delta below is significant (p < 0.001). +Note the ~8× higher absolute per-op cost than the M3 — the GCE vCPU has much +lower single-thread throughput than Apple silicon; the *relative* overhead is +what transfers. + +### Single-threaded (sec/op, vs. baseline) + +| ordering | baseline | minmax | padded | +|------------|----------|-----------------|-----------------| +| steady | 20.86n | 23.00n (+10.3%) | 22.71n (+8.9%) | +| ascending | 20.86n | 22.98n (+10.2%) | 22.68n (+8.7%) | +| descending | 20.88n | 23.02n (+10.3%) | 22.67n (+8.6%) | + +### High contention (sec/op, vs. baseline) + +| ordering | baseline | minmax | padded | +|---------------------|----------|-----------------|------------------| +| g=50, steady | 39.70n | 43.83n (+10.4%) | 44.18n (+11.3%) | +| g=50, ascending | 39.00n | 43.16n (+10.7%) | 43.38n (+11.2%) | +| g=50, descending | 38.91n | 42.97n (+10.4%) | 43.22n (+11.1%) | +| g=100, steady | 39.57n | 43.68n (+10.4%) | 42.93n (+8.5%) | +| g=100, ascending | 39.29n | 42.75n (+8.8%) | 44.46n (+13.2%) | +| g=100, descending | 38.27n | 42.78n (+11.8%) | 44.74n (+16.9%) | ## Findings -1. **Single-threaded overhead is small in absolute terms: ~0.7–0.8 ns/op** - (+25–30% on a ~2.7 ns baseline). Even the adversarial ascending case - (CAS on *every* call) costs only ~0.8 ns more — an uncontended CAS is nearly - as cheap as the guard load, so worst-case ≈ steady-state single-threaded. - -2. **Under contention, inline min/max is effectively free.** In 5 of 6 cases the - inline `minmax` variant is statistically indistinguishable from baseline - (often nominally faster, within noise). The contended `sum.Add` already - dominates the hot path; two read-mostly guard loads that land on an - already-bounced cache line add nothing measurable. Contention runs are noisy - (baseline itself ±10–30%), so treat these as "no detectable regression" - rather than precise deltas. - -3. **Cache-line padding is a pessimization here — the counterintuitive result.** - The `padded` variant is consistently *worse* than inline under contention - (up to +55%). Padding is the standard fix for false sharing, but the extremes - are **read-mostly**: in the inline layout their guard loads piggyback on the - `sum` cache line the core already owns each iteration (it just did `sum.Add`). - Padding moves them onto two *separate* lines that must be fetched - additionally, tripling the hot coherence footprint (1 line → 3). Co-locating - the extremes with the already-hot `sum` is the right call; do **not** pad. +1. **The overhead is real but small and roughly constant per op.** In absolute + terms it's ~0.7–0.8 ns/op on the M3 and ~2.1 ns/op single-threaded / ~4 ns/op + under contention on the GCE x86 worker. As a fraction of `Record` it lands at + **+10% on x86** and +25–30% single-threaded on the (much faster, so + higher-fraction) M3. The x86 run is the trustworthy one for the *relative* + number: its variance is ±0–2% so every delta is significant, whereas the M3's + contention noise (±10–40%) swallowed the signal and made several deltas read + as "no change." + +2. **Input ordering doesn't matter — the guard load makes the CAS nearly free.** + On x86, steady / ascending / descending all cost within ~1% of each other, + single-threaded *and* under 50–100-goroutine contention. Even the adversarial + monotonic orderings (a new extreme on many calls) don't blow up: an + uncontended CAS is about as cheap as the guard load it follows, and under + contention each goroutine replays the same array, so the shared extreme + settles after the first pass and later CAS attempts short-circuit. (A truly + unbounded monotonic stream across all goroutines would contend harder; not + tested here.) + +3. **Cache-line padding is not worth it, and on arm64 it actively hurts.** On + the M3 the padded variant was consistently *worse* than inline under + contention (up to +55%); on x86 it's roughly a wash (±a few %, occasionally + worse at g=100). The extremes are **read-mostly**, so in the inline layout + their guard loads piggyback on the `sum` cache line the core already touches + each iteration (it just did `sum.Add`); padding moves them onto separate + lines that must be fetched additionally. Co-locating with `sum` is at least + as good everywhere and strictly better on arm64 — do **not** pad. ## Recommendation -Exact min/max tracking is cheap enough to add: **~0.8 ns/op single-threaded and -no detectable regression under contention**, zero extra allocations. Use the -**inline** layout (`minmax` variant) and keep the load-guarded CAS. Avoid -cache-line padding. - -If the ~0.8 ns single-threaded cost ever matters on an ultra-hot path, the guard -load is what makes it cheap — no cheaper exact scheme exists (exact extremes -fundamentally require CAS, not fetch-and-add). An approximate alternative would -be to derive min/max from the populated bucket edges at `Snapshot` time for -**zero** hot-path cost, at the price of bucket-width error (≤ the configured -relative error bound) instead of exact values. +Exact min/max tracking is cheap enough to add: a **consistent ~10% `Record` +overhead on x86** (~2–4 ns/op) and low-single-digit ns on Apple silicon, with +zero extra allocations. Use the **inline** layout (`minmax` variant) with the +load-guarded CAS; skip the padding. + +If that ~10% ever matters on an ultra-hot path, note the guard load is already +what keeps it cheap — no cheaper *exact* scheme exists (exact extremes +fundamentally need CAS, not fetch-and-add). The zero-hot-path-cost alternative +is to derive approximate min/max from the populated bucket edges at `Snapshot` +time, trading exactness for bucket-width error (≤ the configured relative error +bound). diff --git a/reports/minmax_raw_amd64.txt b/reports/minmax_raw_amd64.txt new file mode 100644 index 0000000..1ec056c --- /dev/null +++ b/reports/minmax_raw_amd64.txt @@ -0,0 +1,226 @@ +Warning: Identity file /Users/briandillmann/.ssh/google_compute_engine not accessible: Operation not permitted. +Warning: Permanently added '34.148.248.120' (ED25519) to the list of known hosts. +Cloning into 'goodhistogram'... +=== worker: x86_64, 24 cores, go version go1.25.5 linux/amd64 === +goos: linux +goarch: amd64 +pkg: github.com/cockroachdb/goodhistogram +cpu: Intel(R) Xeon(R) CPU @ 2.80GHz +BenchmarkMinMaxSingleThread/order=steady/record-24 57448276 20.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-24 57301809 20.85 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-24 57529870 20.87 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-24 57247857 20.89 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-24 57421759 20.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-24 57189184 20.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-24 57138955 20.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-24 57053180 20.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-24 51920971 22.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-24 52084372 22.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-24 52039462 23.04 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-24 52040611 22.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-24 51807927 23.17 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-24 52067556 23.02 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-24 51948661 22.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-24 51991257 23.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-24 52607277 22.74 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-24 52605135 22.69 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-24 51728493 22.71 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-24 52786579 22.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-24 52739840 22.69 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-24 52833159 22.72 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-24 52814179 22.71 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-24 52704710 22.82 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-24 56938966 20.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-24 57313098 20.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-24 57336224 20.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-24 57445441 20.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-24 57512155 20.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-24 57423139 20.83 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-24 57396774 20.91 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-24 57267397 20.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-24 51433581 22.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-24 51495621 22.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-24 51394417 23.02 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-24 51064740 22.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-24 51284925 22.96 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-24 51397701 23.02 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-24 51412041 22.96 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-24 51536132 22.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-24 52091791 22.72 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-24 51949324 22.76 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-24 52030065 22.66 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-24 51967600 22.64 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-24 51775329 22.69 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-24 52242424 22.69 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-24 52024728 22.66 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-24 51774787 22.66 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-24 57276482 20.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-24 57560128 20.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-24 57022292 20.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-24 56981638 20.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-24 57453252 20.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-24 57547930 20.95 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-24 57519422 20.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-24 57494341 20.87 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-24 51505268 23.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-24 51233070 23.13 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-24 51492116 22.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-24 51392001 22.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-24 51454986 22.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-24 51471405 23.32 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-24 51371032 23.05 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-24 51458346 22.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-24 52005595 22.67 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-24 52163498 22.68 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-24 51805315 22.87 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-24 52213470 22.68 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-24 52216807 22.63 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-24 52149896 22.65 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-24 52097365 22.66 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-24 52127271 22.63 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-24 52081993 39.69 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-24 29619292 39.89 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-24 51765999 40.09 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-24 51103450 40.08 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-24 30752896 39.71 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-24 49383782 39.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-24 51441687 39.08 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-24 51340464 39.30 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-24 26509453 44.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-24 26998356 43.78 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-24 27684817 43.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-24 27326305 43.57 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-24 27391596 44.00 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-24 27063475 43.19 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-24 27533258 43.87 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-24 27135372 43.56 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-24 24504864 42.44 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-24 27186907 45.46 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-24 26096641 42.72 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-24 28302776 45.75 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-24 25783207 42.35 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-24 27758900 45.58 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-24 26225269 42.90 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-24 27522121 45.48 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-24 51623671 38.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-24 52248072 38.68 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-24 51734221 39.18 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-24 52044207 39.15 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-24 51764955 39.01 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-24 52335606 39.10 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-24 28015515 38.68 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-24 52561502 22.68 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-24 24671144 42.85 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-24 27898574 43.25 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-24 27753896 42.57 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-24 27441484 43.34 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-24 27216510 42.67 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-24 27900054 43.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-24 26677032 43.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-24 24241024 44.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-24 25005890 45.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-24 24533078 41.69 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-24 29332824 45.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-24 26430598 41.05 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-24 26805776 45.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-24 26799432 40.68 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-24 28415832 45.13 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-24 25371724 40.55 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-24 49473514 39.82 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-24 51846984 38.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-24 51949099 38.77 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-24 51696159 38.85 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-24 51528228 39.28 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-24 52102538 38.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-24 50769205 22.70 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-24 50453738 39.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-24 25712655 43.49 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-24 25734426 43.31 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-24 26202738 42.75 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-24 27072426 43.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-24 25470444 42.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-24 27578422 42.58 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-24 27446630 43.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-24 26715416 42.48 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-24 26522062 41.27 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-24 27680256 45.46 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-24 26659036 41.00 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-24 27951442 45.74 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-24 25928056 40.59 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-24 28504078 45.17 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-24 28691709 45.39 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-24 24746674 40.61 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-24 50485569 39.56 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-24 51549234 39.41 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-24 51140235 39.82 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-24 51262306 39.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-24 51110376 39.57 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-24 51640120 39.46 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-24 52222792 39.27 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-24 51219258 39.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-24 26577880 45.15 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-24 23169765 43.69 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-24 25578058 44.01 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-24 26676580 43.47 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-24 27926353 43.67 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-24 26991807 43.52 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-24 27629614 43.61 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-24 27250623 44.16 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-24 25594387 45.91 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-24 25307973 43.05 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-24 28474675 45.34 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-24 26382522 42.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-24 28188111 45.73 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-24 26435445 42.81 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-24 26141952 42.77 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-24 28140337 42.61 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-24 47657275 40.08 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-24 49355240 39.01 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-24 52912359 39.54 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-24 52065015 39.53 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-24 51629506 39.38 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-24 51865963 39.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-24 52230640 38.64 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-24 51424269 38.76 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-24 26427514 43.30 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-24 27398674 42.16 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-24 27989769 42.78 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-24 27635350 42.67 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-24 27443670 42.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-24 27938096 43.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-24 26702427 42.72 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-24 27487146 42.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-24 29079151 44.78 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-24 25609038 39.82 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-24 29337481 44.67 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-24 24873205 44.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-24 26313811 40.53 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-24 28656385 44.68 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-24 25655955 40.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-24 29255382 44.26 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-24 51964284 38.61 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-24 52169224 23.02 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-24 50746606 38.60 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-24 52168753 38.16 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-24 48951948 38.39 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-24 51967264 37.91 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-24 53992588 37.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-24 52096189 38.75 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-24 27471246 43.14 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-24 26375866 42.28 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-24 27135022 42.90 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-24 25580972 42.02 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-24 27204883 43.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-24 26850654 42.04 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-24 27445458 43.37 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-24 27163012 42.66 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-24 26120612 40.14 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-24 27796371 44.65 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-24 29964643 44.87 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-24 26325381 44.85 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-24 26377239 44.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-24 26533183 39.64 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-24 27483752 44.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-24 26474415 40.17 ns/op 0 B/op 0 allocs/op +PASS +ok github.com/cockroachdb/goodhistogram 325.147s diff --git a/reports/minmax_raw.txt b/reports/minmax_raw_arm64.txt similarity index 100% rename from reports/minmax_raw.txt rename to reports/minmax_raw_arm64.txt From 2bf26b606b9183c3ae65273ddad36fdd768eaccc Mon Sep 17 00:00:00 2001 From: Brian Dillmann Date: Tue, 18 Aug 2026 15:01:23 -0400 Subject: [PATCH 3/3] goodhistogram: add arm64 server (Ampere Altra) results to min/max perf-eval MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Third architecture: GCE t2a-standard-8 (8 vCPU Ampere Altra, Neoverse N1). Single-thread shows a clean ~+13% Record overhead (consistent with x86's +10%); contention is noisy like the M3. Notably, cache-line padding is a wash here — the "padding hurts" penalty seen on the Apple M3 is M3-specific, not arm64. Co-Authored-By: roachdev-claude --- reports/minmax_benchstat_arm64_server.txt | 33 +++ reports/minmax_perf_eval.md | 97 +++++---- reports/minmax_raw_arm64_server.txt | 235 ++++++++++++++++++++++ 3 files changed, 331 insertions(+), 34 deletions(-) create mode 100644 reports/minmax_benchstat_arm64_server.txt create mode 100644 reports/minmax_raw_arm64_server.txt diff --git a/reports/minmax_benchstat_arm64_server.txt b/reports/minmax_benchstat_arm64_server.txt new file mode 100644 index 0000000..3194ade --- /dev/null +++ b/reports/minmax_benchstat_arm64_server.txt @@ -0,0 +1,33 @@ +arm64 Ampere Altra (GCE t2a-standard-8, 8 vCPU), Go 1.25.5 +Single-threaded (sec/op, vs baseline): + │ sec/op │ sec/op vs base │ sec/op vs base │ +MinMaxSingleThread/order=steady-8 13.36n ± 1% 15.08n ± 1% +12.87% (p=0.000 n=8) 15.05n ± 1% +12.65% (p=0.000 n=8) +MinMaxSingleThread/order=ascending-8 13.30n ± 1% 15.03n ± 0% +13.01% (p=0.000 n=8) 15.04n ± 1% +13.08% (p=0.000 n=8) +MinMaxSingleThread/order=descending-8 13.21n ± 1% 15.04n ± 0% +13.86% (p=0.000 n=8) 14.99n ± 1% +13.48% (p=0.000 n=8) +MinMaxSingleThread/order=steady-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=ascending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=descending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=steady-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=ascending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxSingleThread/order=descending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ + +Contention (sec/op, vs baseline): + │ sec/op │ sec/op vs base │ sec/op vs base │ +MinMaxContention/g=50/order=steady-8 101.80n ± 5% 94.53n ± 3% -7.14% (p=0.001 n=8) 94.58n ± 9% -7.09% (p=0.050 n=8) +MinMaxContention/g=50/order=ascending-8 82.21n ± 5% 88.98n ± 7% +8.24% (p=0.021 n=8) 85.47n ± 12% ~ (p=0.053 n=8) +MinMaxContention/g=50/order=descending-8 81.88n ± 13% 94.33n ± 9% +15.21% (p=0.015 n=8) 87.97n ± 4% ~ (p=0.279 n=8) +MinMaxContention/g=100/order=steady-8 100.19n ± 5% 96.70n ± 11% ~ (p=0.425 n=8) 100.12n ± 5% ~ (p=0.777 n=8) +MinMaxContention/g=100/order=ascending-8 97.99n ± 6% 99.46n ± 9% ~ (p=0.818 n=8) 98.52n ± 6% ~ (p=0.857 n=8) +MinMaxContention/g=100/order=descending-8 97.34n ± 39% 99.88n ± 13% ~ (p=0.902 n=8) 95.94n ± 9% ~ (p=0.878 n=8) +MinMaxContention/g=50/order=steady-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=ascending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=descending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=steady-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=ascending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=descending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=steady-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=ascending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=50/order=descending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=steady-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=ascending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ +MinMaxContention/g=100/order=descending-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=8) ¹ 0.000 ± 0% ~ (p=1.000 n=8) ¹ diff --git a/reports/minmax_perf_eval.md b/reports/minmax_perf_eval.md index 91a8b86..4c4f611 100644 --- a/reports/minmax_perf_eval.md +++ b/reports/minmax_perf_eval.md @@ -39,10 +39,12 @@ independent variable: every call. Adversarial worst case. - **descending** — monotonically decreasing: every `Record` sets a new min. -Run on two machines, schema 2, range [500, 6e10], `-count=8`: -- **arm64** — Apple M3 Pro (laptop). Raw: `minmax_raw_arm64.txt`; benchstat: `minmax_benchstat_arm64.txt`. -- **amd64** — GCE worker `gceworker-briandillmann`, 24 vCPU x86_64, Go 1.25.5. +Run on three machines, schema 2, range [500, 6e10], `-count=8`: +- **arm64 (laptop)** — Apple M3 Pro. Raw: `minmax_raw_arm64.txt`; benchstat: `minmax_benchstat_arm64.txt`. +- **amd64 (server)** — GCE `gceworker-briandillmann`, 24 vCPU x86_64, Go 1.25.5. Raw: `minmax_raw_amd64.txt`; benchstat: `minmax_benchstat_amd64.txt`. +- **arm64 (server)** — GCE `t2a-standard-8`, 8 vCPU Ampere Altra (Neoverse N1), Go 1.25.5. + Raw: `minmax_raw_arm64_server.txt`; benchstat: `minmax_benchstat_arm64_server.txt`. ## Results — arm64 (Apple M3 Pro) @@ -94,42 +96,69 @@ what transfers. | g=100, ascending | 39.29n | 42.75n (+8.8%) | 44.46n (+13.2%) | | g=100, descending | 38.27n | 42.78n (+11.8%) | 44.74n (+16.9%) | +## Results — arm64 server (GCE t2a-standard-8, 8 vCPU Ampere Altra) + +Single-thread variance is tight (±1%); contention is noisy like the M3. + +### Single-threaded (sec/op, vs. baseline) + +| ordering | baseline | minmax | padded | +|------------|----------|-----------------|-----------------| +| steady | 13.36n | 15.08n (+12.9%) | 15.05n (+12.7%) | +| ascending | 13.30n | 15.03n (+13.0%) | 15.04n (+13.1%) | +| descending | 13.21n | 15.04n (+13.9%) | 14.99n (+13.5%) | + +### High contention (sec/op, vs. baseline) + +| ordering | baseline | minmax | padded | +|---------------------|----------|-----------------|-----------------| +| g=50, steady | 101.8n | 94.5n (−7.1%) | 94.6n (−7.1%) | +| g=50, ascending | 82.2n | 89.0n (+8.2%) | 85.5n (~, n.s.) | +| g=50, descending | 81.9n | 94.3n (+15.2%) | 88.0n (~, n.s.) | +| g=100, steady | 100.2n | 96.7n (~, n.s.) | 100.1n (~, n.s.)| +| g=100, ascending | 98.0n | 99.5n (~, n.s.) | 98.5n (~, n.s.) | +| g=100, descending | 97.3n | 99.9n (~, n.s.) | 95.9n (~, n.s.) | + ## Findings -1. **The overhead is real but small and roughly constant per op.** In absolute - terms it's ~0.7–0.8 ns/op on the M3 and ~2.1 ns/op single-threaded / ~4 ns/op - under contention on the GCE x86 worker. As a fraction of `Record` it lands at - **+10% on x86** and +25–30% single-threaded on the (much faster, so - higher-fraction) M3. The x86 run is the trustworthy one for the *relative* - number: its variance is ±0–2% so every delta is significant, whereas the M3's - contention noise (±10–40%) swallowed the signal and made several deltas read - as "no change." - -2. **Input ordering doesn't matter — the guard load makes the CAS nearly free.** - On x86, steady / ascending / descending all cost within ~1% of each other, - single-threaded *and* under 50–100-goroutine contention. Even the adversarial - monotonic orderings (a new extreme on many calls) don't blow up: an - uncontended CAS is about as cheap as the guard load it follows, and under - contention each goroutine replays the same array, so the shared extreme - settles after the first pass and later CAS attempts short-circuit. (A truly - unbounded monotonic stream across all goroutines would contend harder; not - tested here.) - -3. **Cache-line padding is not worth it, and on arm64 it actively hurts.** On - the M3 the padded variant was consistently *worse* than inline under - contention (up to +55%); on x86 it's roughly a wash (±a few %, occasionally - worse at g=100). The extremes are **read-mostly**, so in the inline layout - their guard loads piggyback on the `sum` cache line the core already touches - each iteration (it just did `sum.Add`); padding moves them onto separate - lines that must be fetched additionally. Co-locating with `sum` is at least - as good everywhere and strictly better on arm64 — do **not** pad. +1. **Single-threaded overhead is real, small, and consistent — ~10–13% of + `Record` across all three machines** (steady state): +10% on x86 server, + +13% on Ampere arm server, +26% on the M3 (higher only because the M3's + baseline `Record` is ~5–8× faster in absolute terms, so a fixed ~0.7 ns costs + a bigger fraction). In absolute terms it's ~0.7 ns/op (M3), ~1.7 ns/op + (Ampere), ~2.1 ns/op (x86). The two server runs have tight ±1% variance so + every single-thread delta is significant. + +2. **Under contention the cost disappears into the noise.** Only the x86 server + shows a clean, consistent +10% under contention; both arm machines (M3 and + Ampere) are too noisy (±5–40%) to distinguish min/max from baseline — several + deltas are even negative. The contended `sum.Add` already dominates, so the + read-mostly guard loads add little. Treat contention as "no clear regression." + +3. **Input ordering doesn't matter — the guard load makes the CAS nearly free.** + steady / ascending / descending land within ~1% of each other single-threaded + on both server machines. Even the adversarial monotonic orderings (a new + extreme on many calls) don't blow up: an uncontended CAS is about as cheap as + the guard load it follows, and under contention each goroutine replays the + same array, so the shared extreme settles after the first pass and later CAS + attempts short-circuit. (A truly unbounded global monotonic stream would + contend harder; not tested.) + +4. **Cache-line padding isn't worth it — and the "padding hurts" effect is + Apple-M3-specific, not arm64-general.** On the M3 the padded variant was + consistently *worse* than inline under contention (up to +55%); but on the + Ampere arm server padding is a wash (within noise), same as x86. So the + dramatic penalty was an M3 quirk, not an arm property. Everywhere, co-locating + the read-mostly extremes with the already-hot `sum` cache line (inline) is at + least as good as padding and never worse — so **don't pad**. ## Recommendation -Exact min/max tracking is cheap enough to add: a **consistent ~10% `Record` -overhead on x86** (~2–4 ns/op) and low-single-digit ns on Apple silicon, with -zero extra allocations. Use the **inline** layout (`minmax` variant) with the -load-guarded CAS; skip the padding. +Exact min/max tracking is cheap enough to add: a **~10–13% single-threaded +`Record` overhead** (~0.7–2 ns/op, consistent across x86 and arm servers and the +M3 laptop), **no clear regression under contention**, and zero extra +allocations. Use the **inline** layout (`minmax` variant) with the load-guarded +CAS; skip the padding. If that ~10% ever matters on an ultra-hot path, note the guard load is already what keeps it cheap — no cheaper *exact* scheme exists (exact extremes diff --git a/reports/minmax_raw_arm64_server.txt b/reports/minmax_raw_arm64_server.txt new file mode 100644 index 0000000..36119f1 --- /dev/null +++ b/reports/minmax_raw_arm64_server.txt @@ -0,0 +1,235 @@ +go: downloading github.com/prometheus/client_golang v1.23.2 +go: downloading github.com/prometheus/client_model v0.6.2 +go: downloading github.com/stretchr/testify v1.11.1 +go: downloading google.golang.org/protobuf v1.36.8 +go: downloading github.com/davecgh/go-spew v1.1.1 +go: downloading github.com/pmezard/go-difflib v1.0.0 +go: downloading gopkg.in/yaml.v3 v3.0.1 +go: downloading github.com/prometheus/common v0.66.1 +go: downloading github.com/beorn7/perks v1.0.1 +go: downloading github.com/cespare/xxhash/v2 v2.3.0 +go: downloading github.com/prometheus/procfs v0.16.1 +go: downloading github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 +go: downloading go.yaml.in/yaml/v2 v2.4.2 +go: downloading golang.org/x/sys v0.35.0 +goos: linux +goarch: arm64 +pkg: github.com/cockroachdb/goodhistogram +BenchmarkMinMaxSingleThread/order=steady/record-8 89521854 13.32 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-8 89424987 13.35 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-8 89879911 13.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-8 89547506 13.31 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-8 89067895 13.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-8 89465250 13.37 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-8 88802664 13.44 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-8 88975965 13.34 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-8 79164309 15.06 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-8 79579681 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-8 78639916 15.02 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-8 79678380 15.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-8 79128390 15.01 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-8 79934415 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-8 78836442 15.00 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-minmax-8 79815115 15.10 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-8 79208202 14.96 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-8 80003701 15.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-8 78410943 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-8 79103983 14.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-8 79819782 14.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-8 79346044 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-8 78480276 14.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=steady/record-padded-8 78833546 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-8 90951616 13.40 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-8 89670362 13.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-8 89976146 13.42 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-8 88537179 13.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-8 91082229 13.38 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-8 89622144 13.22 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-8 90602223 13.39 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-8 89845186 13.21 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-8 76521700 14.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-8 76774518 15.10 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-8 75824659 14.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-8 76708362 15.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-8 76811670 14.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-8 76293624 15.10 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-8 76231780 14.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-minmax-8 77058096 15.08 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-8 76217449 15.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-8 76348573 14.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-8 77195701 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-8 76478784 14.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-8 76195962 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-8 76604577 14.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-8 76941916 15.09 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=ascending/record-padded-8 76100508 14.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-8 89914189 13.21 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-8 90777758 13.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-8 91277401 13.38 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-8 88968643 13.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-8 91036141 13.40 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-8 89167765 13.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-8 90841530 13.41 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-8 89869208 13.20 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-8 75955803 14.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-8 76434187 15.06 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-8 76036466 15.01 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-8 76337334 15.06 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-8 75698407 14.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-8 76284147 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-8 75426816 14.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-minmax-8 76371342 15.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-8 75470078 14.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-8 75009090 15.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-8 75264644 14.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-8 75702228 14.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-8 75808396 15.11 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-8 75644199 14.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-8 76538518 15.14 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxSingleThread/order=descending/record-padded-8 75427200 14.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-8 19781232 102.0 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-8 19222936 107.1 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-8 20516773 99.49 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-8 20974554 96.82 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-8 19766899 105.2 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-8 21624564 102.5 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-8 11867691 101.1 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-8 21510104 101.6 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-8 11946811 95.00 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-8 13418262 91.47 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-8 13143856 91.45 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-8 12824150 95.82 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-8 12594732 100.8 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-8 13743326 95.83 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-8 12761194 94.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-minmax-8 12932263 93.09 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-8 20401658 92.66 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-8 18857780 90.03 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-8 20428015 92.46 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-8 17850171 93.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-8 18399045 96.09 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-8 18430604 97.89 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-8 20888845 103.0 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=steady/record-padded-8 21670755 103.6 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-8 18209271 80.38 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-8 18198274 81.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-8 20600263 79.27 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-8 21652948 101.3 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-8 21542937 82.55 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-8 16976269 80.36 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-8 20075672 83.04 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-8 20875950 86.71 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-8 11409374 93.45 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-8 12362994 83.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-8 12885217 95.47 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-8 12790713 89.58 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-8 11892913 86.14 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-8 11748103 96.65 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-8 13112509 87.59 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-minmax-8 14759407 88.37 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-8 19279108 96.05 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-8 20279416 88.80 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-8 19831020 83.04 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-8 19125096 95.96 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-8 17376006 83.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-8 18551047 84.25 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-8 19180498 83.36 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=ascending/record-padded-8 20414865 86.70 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-8 20183690 81.27 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-8 19224519 81.78 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-8 21444002 81.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-8 21048644 80.13 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-8 19723640 92.45 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-8 21084867 94.93 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-8 21565056 81.52 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-8 21348560 89.95 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-8 13520998 92.22 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-8 11565877 103.8 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-8 14227152 94.17 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-8 13784160 94.49 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-8 13730238 85.51 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-8 14029747 91.01 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-8 10922265 101.7 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-minmax-8 11025698 95.24 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-8 18884462 98.44 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-8 19536105 85.57 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-8 18450204 88.28 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-8 19007260 84.23 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-8 19436941 84.63 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-8 18679945 89.83 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-8 19532145 87.84 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=50/order=descending/record-padded-8 19270262 88.09 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-8 21761232 96.88 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-8 21116926 97.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-8 19221408 103.1 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-8 16666706 103.1 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-8 21489573 95.37 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-8 19029020 105.9 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-8 20765031 97.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-8 20570764 104.5 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-8 12264748 96.40 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-8 12461361 101.0 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-8 12017359 85.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-8 14563880 97.00 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-8 12547420 94.04 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-8 12296233 106.5 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-8 11481475 96.29 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-minmax-8 12553821 106.3 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-8 17468978 107.9 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-8 18246391 97.21 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-8 19578447 105.4 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-8 20573355 101.9 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-8 20121483 97.57 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-8 18649448 101.3 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-8 22148720 96.53 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=steady/record-padded-8 20712118 98.95 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-8 19402495 92.26 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-8 21572067 97.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-8 20175584 104.7 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-8 22280818 101.7 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-8 19600310 96.97 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-8 17294833 97.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-8 19030326 97.96 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-8 19483339 99.89 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-8 12534699 111.3 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-8 10564398 96.63 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-8 12330028 102.3 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-8 12512036 93.98 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-8 13658676 104.7 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-8 11291824 93.71 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-8 12754444 108.3 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-minmax-8 11389965 94.50 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-8 18024717 101.9 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-8 18434400 96.63 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-8 17990991 92.99 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-8 17736339 97.91 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-8 21416542 94.67 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-8 18184627 99.12 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-8 20816811 103.9 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=ascending/record-padded-8 19997388 101.6 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-8 21382392 97.73 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-8 21579658 102.1 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-8 21333946 94.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-8 21043980 59.07 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-8 22760083 104.6 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-8 21753192 94.67 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-8 20930528 102.5 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-8 19915111 96.94 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-8 12874021 87.56 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-8 13395696 86.89 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-8 11249469 94.83 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-8 13426441 102.1 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-8 11625711 101.7 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-8 11923626 100.3 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-8 12419366 99.47 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-minmax-8 14240679 101.1 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-8 19848553 92.86 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-8 21949486 101.0 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-8 20018253 94.10 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-8 20516056 96.43 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-8 19652360 106.2 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-8 23714835 95.44 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-8 17246964 92.71 ns/op 0 B/op 0 allocs/op +BenchmarkMinMaxContention/g=100/order=descending/record-padded-8 19215802 104.7 ns/op 0 B/op 0 allocs/op +PASS +ok github.com/cockroachdb/goodhistogram 407.529s