]> Cypherpunks repositories - gostls13.git/commitdiff
math/big: add tests for allocation during multiply
authorRuss Cox <rsc@golang.org>
Fri, 14 Feb 2025 17:52:02 +0000 (12:52 -0500)
committerGopher Robot <gobot@golang.org>
Thu, 27 Feb 2025 14:05:02 +0000 (06:05 -0800)
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>

src/math/big/escape_test.go [new file with mode: 0644]

diff --git a/src/math/big/escape_test.go b/src/math/big/escape_test.go
new file mode 100644 (file)
index 0000000..1e757f5
--- /dev/null
@@ -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)
+               }
+       }
+}