aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2022-06-17 19:56:27 +0000
committerGopher Robot <gobot@golang.org>2022-06-21 19:37:22 +0000
commit4b236b45d0bb659a447dcfc02ebd431587b52e2b (patch)
treeb65509093e8324d051252a22c265950c624ed847 /src/internal
parent530511bacccdea0bb8a0fec644887c2613535c50 (diff)
downloadgo-4b236b45d0bb659a447dcfc02ebd431587b52e2b.tar.xz
runtime: convert flaky semaphore linearity test into benchmark
Also, add a benchmark for another case that was originally tested. Also also, remove all the dead code this now creates. Fixes #53428. Change-Id: Idbba88d3d31d38a8854fd5ed99001e394da27300 Reviewed-on: https://go-review.googlesource.com/c/go/+/412878 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> Auto-Submit: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/testenv/testenv.go65
-rw-r--r--src/internal/testmath/bench.go38
-rw-r--r--src/internal/testmath/ttest.go213
3 files changed, 0 insertions, 316 deletions
diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go
index b7cb95063b..1feb630cf5 100644
--- a/src/internal/testenv/testenv.go
+++ b/src/internal/testenv/testenv.go
@@ -16,7 +16,6 @@ import (
"flag"
"fmt"
"internal/cfg"
- "internal/testmath"
"os"
"os/exec"
"path/filepath"
@@ -464,67 +463,3 @@ func RunWithTimeout(t testing.TB, cmd *exec.Cmd) ([]byte, error) {
return b.Bytes(), err
}
-
-// CheckLinear checks if the function produced by f scales linearly.
-//
-// f must accept a scale factor which causes the input to the function it
-// produces to scale by that factor.
-func CheckLinear(t *testing.T, f func(scale float64) func(*testing.B)) {
- MustHaveExec(t)
-
- if os.Getenv("GO_PERF_UNIT_TEST") == "" {
- // Invoke the same test as a subprocess with the GO_PERF_UNIT_TEST environment variable set.
- // We create a subprocess for two reasons:
- //
- // 1. There's no other way to set the benchmarking parameters of testing.Benchmark.
- // 2. Since we're effectively running a performance test, running in a subprocess grants
- // us a little bit more isolation than using the same process.
- //
- // As an alternative, we could fairly easily reimplement the timing code in testing.Benchmark,
- // but a subprocess is just as easy to create.
-
- selfCmd := CleanCmdEnv(exec.Command(os.Args[0], "-test.v", fmt.Sprintf("-test.run=^%s$", t.Name()), "-test.benchtime=1x"))
- selfCmd.Env = append(selfCmd.Env, "GO_PERF_UNIT_TEST=1")
- output, err := RunWithTimeout(t, selfCmd)
- if err != nil {
- t.Error(err)
- t.Logf("--- subprocess output ---\n%s", string(output))
- }
- if bytes.Contains(output, []byte("insignificant result")) {
- t.Skip("insignificant result")
- }
- return
- }
-
- // Pick a reasonable sample count.
- const count = 10
-
- // Collect samples for scale factor 1.
- x1 := make([]testing.BenchmarkResult, 0, count)
- for i := 0; i < count; i++ {
- x1 = append(x1, testing.Benchmark(f(1.0)))
- }
-
- // Collect samples for scale factor 2.
- x2 := make([]testing.BenchmarkResult, 0, count)
- for i := 0; i < count; i++ {
- x2 = append(x2, testing.Benchmark(f(2.0)))
- }
-
- // Run a t-test on the results.
- r1 := testmath.BenchmarkResults(x1)
- r2 := testmath.BenchmarkResults(x2)
- result, err := testmath.TwoSampleWelchTTest(r1, r2, testmath.LocationDiffers)
- if err != nil {
- t.Fatalf("failed to run t-test: %v", err)
- }
- if result.P > 0.005 {
- // Insignificant result.
- t.Skip("insignificant result")
- }
-
- // Let ourselves be within 3x; 2x is too strict.
- if m1, m2 := r1.Mean(), r2.Mean(); 3.0*m1 < m2 {
- t.Fatalf("failure to scale linearly: µ_1=%s µ_2=%s p=%f", time.Duration(m1), time.Duration(m2), result.P)
- }
-}
diff --git a/src/internal/testmath/bench.go b/src/internal/testmath/bench.go
deleted file mode 100644
index 6f034b4685..0000000000
--- a/src/internal/testmath/bench.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package testmath
-
-import (
- "math"
- "testing"
- "time"
-)
-
-type BenchmarkResults []testing.BenchmarkResult
-
-func (b BenchmarkResults) Weight() float64 {
- var weight int
- for _, r := range b {
- weight += r.N
- }
- return float64(weight)
-}
-
-func (b BenchmarkResults) Mean() float64 {
- var dur time.Duration
- for _, r := range b {
- dur += r.T * time.Duration(r.N)
- }
- return float64(dur) / b.Weight()
-}
-
-func (b BenchmarkResults) Variance() float64 {
- var num float64
- mean := b.Mean()
- for _, r := range b {
- num += math.Pow(float64(r.T)-mean, 2) * float64(r.N)
- }
- return float64(num) / b.Weight()
-}
diff --git a/src/internal/testmath/ttest.go b/src/internal/testmath/ttest.go
deleted file mode 100644
index d15d2deebb..0000000000
--- a/src/internal/testmath/ttest.go
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2022 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package testmath
-
-import (
- "errors"
- "math"
-)
-
-// A TTestSample is a sample that can be used for a one or two sample
-// t-test.
-type TTestSample interface {
- Weight() float64
- Mean() float64
- Variance() float64
-}
-
-var (
- ErrSampleSize = errors.New("sample is too small")
- ErrZeroVariance = errors.New("sample has zero variance")
- ErrMismatchedSamples = errors.New("samples have different lengths")
-)
-
-// TwoSampleWelchTTest performs a two-sample (unpaired) Welch's t-test
-// on samples x1 and x2. This t-test does not assume the distributions
-// have equal variance.
-func TwoSampleWelchTTest(x1, x2 TTestSample, alt LocationHypothesis) (*TTestResult, error) {
- n1, n2 := x1.Weight(), x2.Weight()
- if n1 <= 1 || n2 <= 1 {
- // TODO: Can we still do this with n == 1?
- return nil, ErrSampleSize
- }
- v1, v2 := x1.Variance(), x2.Variance()
- if v1 == 0 && v2 == 0 {
- return nil, ErrZeroVariance
- }
-
- dof := math.Pow(v1/n1+v2/n2, 2) /
- (math.Pow(v1/n1, 2)/(n1-1) + math.Pow(v2/n2, 2)/(n2-1))
- s := math.Sqrt(v1/n1 + v2/n2)
- t := (x1.Mean() - x2.Mean()) / s
- return newTTestResult(int(n1), int(n2), t, dof, alt), nil
-}
-
-// A TTestResult is the result of a t-test.
-type TTestResult struct {
- // N1 and N2 are the sizes of the input samples. For a
- // one-sample t-test, N2 is 0.
- N1, N2 int
-
- // T is the value of the t-statistic for this t-test.
- T float64
-
- // DoF is the degrees of freedom for this t-test.
- DoF float64
-
- // AltHypothesis specifies the alternative hypothesis tested
- // by this test against the null hypothesis that there is no
- // difference in the means of the samples.
- AltHypothesis LocationHypothesis
-
- // P is p-value for this t-test for the given null hypothesis.
- P float64
-}
-
-func newTTestResult(n1, n2 int, t, dof float64, alt LocationHypothesis) *TTestResult {
- dist := TDist{dof}
- var p float64
- switch alt {
- case LocationDiffers:
- p = 2 * (1 - dist.CDF(math.Abs(t)))
- case LocationLess:
- p = dist.CDF(t)
- case LocationGreater:
- p = 1 - dist.CDF(t)
- }
- return &TTestResult{N1: n1, N2: n2, T: t, DoF: dof, AltHypothesis: alt, P: p}
-}
-
-// A LocationHypothesis specifies the alternative hypothesis of a
-// location test such as a t-test or a Mann-Whitney U-test. The
-// default (zero) value is to test against the alternative hypothesis
-// that they differ.
-type LocationHypothesis int
-
-const (
- // LocationLess specifies the alternative hypothesis that the
- // location of the first sample is less than the second. This
- // is a one-tailed test.
- LocationLess LocationHypothesis = -1
-
- // LocationDiffers specifies the alternative hypothesis that
- // the locations of the two samples are not equal. This is a
- // two-tailed test.
- LocationDiffers LocationHypothesis = 0
-
- // LocationGreater specifies the alternative hypothesis that
- // the location of the first sample is greater than the
- // second. This is a one-tailed test.
- LocationGreater LocationHypothesis = 1
-)
-
-// A TDist is a Student's t-distribution with V degrees of freedom.
-type TDist struct {
- V float64
-}
-
-// PDF returns the value at x of the probability distribution function for the
-// distribution.
-func (t TDist) PDF(x float64) float64 {
- return math.Exp(lgamma((t.V+1)/2)-lgamma(t.V/2)) /
- math.Sqrt(t.V*math.Pi) * math.Pow(1+(x*x)/t.V, -(t.V+1)/2)
-}
-
-// CDF returns the value at x of the cumulative distribution function for the
-// distribution.
-func (t TDist) CDF(x float64) float64 {
- if x == 0 {
- return 0.5
- } else if x > 0 {
- return 1 - 0.5*betaInc(t.V/(t.V+x*x), t.V/2, 0.5)
- } else if x < 0 {
- return 1 - t.CDF(-x)
- } else {
- return math.NaN()
- }
-}
-
-func (t TDist) Bounds() (float64, float64) {
- return -4, 4
-}
-
-func lgamma(x float64) float64 {
- y, _ := math.Lgamma(x)
- return y
-}
-
-// betaInc returns the value of the regularized incomplete beta
-// function Iₓ(a, b) = 1 / B(a, b) * ∫₀ˣ tᵃ⁻¹ (1-t)ᵇ⁻¹ dt.
-//
-// This is not to be confused with the "incomplete beta function",
-// which can be computed as BetaInc(x, a, b)*Beta(a, b).
-//
-// If x < 0 or x > 1, returns NaN.
-func betaInc(x, a, b float64) float64 {
- // Based on Numerical Recipes in C, section 6.4. This uses the
- // continued fraction definition of I:
- //
- // (xᵃ*(1-x)ᵇ)/(a*B(a,b)) * (1/(1+(d₁/(1+(d₂/(1+...))))))
- //
- // where B(a,b) is the beta function and
- //
- // d_{2m+1} = -(a+m)(a+b+m)x/((a+2m)(a+2m+1))
- // d_{2m} = m(b-m)x/((a+2m-1)(a+2m))
- if x < 0 || x > 1 {
- return math.NaN()
- }
- bt := 0.0
- if 0 < x && x < 1 {
- // Compute the coefficient before the continued
- // fraction.
- bt = math.Exp(lgamma(a+b) - lgamma(a) - lgamma(b) +
- a*math.Log(x) + b*math.Log(1-x))
- }
- if x < (a+1)/(a+b+2) {
- // Compute continued fraction directly.
- return bt * betacf(x, a, b) / a
- } else {
- // Compute continued fraction after symmetry transform.
- return 1 - bt*betacf(1-x, b, a)/b
- }
-}
-
-// betacf is the continued fraction component of the regularized
-// incomplete beta function Iₓ(a, b).
-func betacf(x, a, b float64) float64 {
- const maxIterations = 200
- const epsilon = 3e-14
-
- raiseZero := func(z float64) float64 {
- if math.Abs(z) < math.SmallestNonzeroFloat64 {
- return math.SmallestNonzeroFloat64
- }
- return z
- }
-
- c := 1.0
- d := 1 / raiseZero(1-(a+b)*x/(a+1))
- h := d
- for m := 1; m <= maxIterations; m++ {
- mf := float64(m)
-
- // Even step of the recurrence.
- numer := mf * (b - mf) * x / ((a + 2*mf - 1) * (a + 2*mf))
- d = 1 / raiseZero(1+numer*d)
- c = raiseZero(1 + numer/c)
- h *= d * c
-
- // Odd step of the recurrence.
- numer = -(a + mf) * (a + b + mf) * x / ((a + 2*mf) * (a + 2*mf + 1))
- d = 1 / raiseZero(1+numer*d)
- c = raiseZero(1 + numer/c)
- hfac := d * c
- h *= hfac
-
- if math.Abs(hfac-1) < epsilon {
- return h
- }
- }
- panic("betainc: a or b too big; failed to converge")
-}