From 2b737073587cb8f82d41fa96fdec9e56a5bac8ba Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 14 Feb 2025 12:52:02 -0500 Subject: [PATCH] math/big: add tests for allocation during multiply Test that big.Int.Mul reusing the same target is not allocating temporary garbage during its computation. That code is going to be modified in an upcoming CL. Change-Id: I3ed55c06da030282233c29cd7af2a04f395dc7a2 Reviewed-on: https://go-review.googlesource.com/c/go/+/652056 LUCI-TryBot-Result: Go LUCI Reviewed-by: Alan Donovan Auto-Submit: Russ Cox --- src/math/big/escape_test.go | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/math/big/escape_test.go diff --git a/src/math/big/escape_test.go b/src/math/big/escape_test.go new file mode 100644 index 0000000000..1e757f55ab --- /dev/null +++ b/src/math/big/escape_test.go @@ -0,0 +1,53 @@ +// Copyright 2025 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 big + +import ( + "internal/testenv" + "math/rand" + "os/exec" + "strings" + "testing" +) + +func TestEscape(t *testing.T) { + testenv.MustHaveGoBuild(t) + // The multiplication routines create many temporary Int values, + // expecting them to be stack-allocated. Make sure none escape to the heap. + out, err := exec.Command("go", "build", "-gcflags=-m").CombinedOutput() + if err != nil { + t.Fatalf("go build -gcflags=-m: %v\n%s", err, out) + } + for line := range strings.Lines(string(out)) { + if strings.Contains(line, "natmul.go") && strings.Contains(line, "Int") && strings.Contains(line, "escapes") { + t.Error(strings.TrimSpace(line)) + } + } +} + +func TestMulAlloc(t *testing.T) { + r := rand.New(rand.NewSource(1234)) + sizes := []int{karatsubaThreshold / 2, karatsubaThreshold} + for _, size := range sizes { + x := randInt(r, uint(size)) + y := randInt(r, uint(size)) + z := &Int{abs: make(nat, 2*uint(size))} + if n := testing.AllocsPerRun(10, func() { z.Mul(x, y) }); n >= 1 { + t.Errorf("Mul(len %d, len %d) allocates %.2f objects", size, size, n) + } + } +} + +func TestSqrAlloc(t *testing.T) { + r := rand.New(rand.NewSource(1234)) + sizes := []int{basicSqrThreshold / 2, basicSqrThreshold, karatsubaSqrThreshold} + for _, size := range sizes { + x := randInt(r, uint(size)) + z := &Int{abs: make(nat, 2*uint(size))} + if n := testing.AllocsPerRun(10, func() { z.Mul(x, x) }); n >= 1 { + t.Errorf("Mul(len %d with itself) allocates %.2f objects", size, n) + } + } +} -- 2.50.0