aboutsummaryrefslogtreecommitdiff
path: root/src/math
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2025-02-14 12:52:02 -0500
committerGopher Robot <gobot@golang.org>2025-02-27 06:05:02 -0800
commit2b737073587cb8f82d41fa96fdec9e56a5bac8ba (patch)
tree0780d669fc56c0ddb8c6afa959b207c2a2bd5d17 /src/math
parent0ab2253ce1e9183c2cb94f3a594448320cb65962 (diff)
downloadgo-2b737073587cb8f82d41fa96fdec9e56a5bac8ba.tar.xz
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 <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Alan Donovan <adonovan@google.com> Auto-Submit: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/math')
-rw-r--r--src/math/big/escape_test.go53
1 files changed, 53 insertions, 0 deletions
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)
+ }
+ }
+}