util/deephash: fix TestArrayAllocs

Unfortunately this test fails on certain architectures.
The problem comes down to inconsistencies in the Go escape analysis
where specific variables are marked as escaping on certain architectures.
The variables escaping to the heap are unfortunately in crypto/sha256,
which makes it impossible to fixthis locally in deephash.

For now, fix the test by compensating for the allocations that
occur from calling sha256.digest.Sum.

See golang/go#48055

Fixes #2727

Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
Joe Tsai 2021-08-30 10:47:21 -07:00 committed by GitHub
parent 30458c71c8
commit 3f1317e3e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -8,9 +8,11 @@
"archive/tar" "archive/tar"
"bufio" "bufio"
"bytes" "bytes"
"crypto/sha256"
"fmt" "fmt"
"math" "math"
"reflect" "reflect"
"runtime"
"testing" "testing"
"inet.af/netaddr" "inet.af/netaddr"
@ -332,15 +334,32 @@ func TestArrayAllocs(t *testing.T) {
if version.IsRace() { if version.IsRace() {
t.Skip("skipping test under race detector") t.Skip("skipping test under race detector")
} }
// In theory, there should be no allocations. However, escape analysis on
// certain architectures fails to detect that certain cases do not escape.
// This discrepency currently affects sha256.digest.Sum.
// Measure the number of allocations in sha256 to ensure that Hash does
// not allocate on top of its usage of sha256.
// See https://golang.org/issue/48055.
var b []byte
h := sha256.New()
want := int(testing.AllocsPerRun(1000, func() {
b = h.Sum(b[:0])
}))
switch runtime.GOARCH {
case "amd64", "arm64":
want = 0 // ensure no allocations on popular architectures
}
type T struct { type T struct {
X [32]byte X [32]byte
} }
x := &T{X: [32]byte{1: 1, 2: 2, 3: 3, 4: 4}} x := &T{X: [32]byte{1: 1, 2: 2, 3: 3, 4: 4}}
n := int(testing.AllocsPerRun(1000, func() { got := int(testing.AllocsPerRun(1000, func() {
sink = Hash(x) sink = Hash(x)
})) }))
if n > 0 { if got > want {
t.Errorf("allocs = %v; want 0", n) t.Errorf("allocs = %v; want %v", got, want)
} }
} }