Skip to content

Commit d9c3aea

Browse files
authored
Basic chore cleanups of tests and benchmarks (#66)
* Upgrade cpuid, regen buildtags * Move all uses of cpuid to one place, adjust benchmarks * Rename SIMD functions to match instruction set * One more rename, align arch-specific files
1 parent 99e45fa commit d9c3aea

14 files changed

+94
-90
lines changed

cpuid_other.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ import (
2323
"github.com/klauspost/cpuid/v2"
2424
)
2525

26+
var (
27+
hasIntelSha = runtime.GOARCH == "amd64" && cpuid.CPU.Supports(cpuid.SHA, cpuid.SSSE3, cpuid.SSE4)
28+
hasAvx512 = cpuid.CPU.Supports(cpuid.AVX512F, cpuid.AVX512DQ, cpuid.AVX512BW, cpuid.AVX512VL)
29+
)
30+
2631
func hasArmSha2() bool {
2732
if cpuid.CPU.Has(cpuid.SHA2) {
2833
return true
@@ -42,5 +47,4 @@ func hasArmSha2() bool {
4247
return false
4348
}
4449
return bytes.Contains(cpuInfo, []byte(sha256Feature))
45-
4650
}

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ module github.com/minio/sha256-simd
22

33
go 1.13
44

5-
require github.com/klauspost/cpuid/v2 v2.0.6
5+
require github.com/klauspost/cpuid/v2 v2.2.3

go.sum

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
2-
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
1+
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
2+
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
3+
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e h1:CsOuNlbOuf0mzxJIefr6Q4uAUetRUwZE4qt7VfzP+xo=
4+
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

sha256.go

+20-31
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ import (
2020
"crypto/sha256"
2121
"encoding/binary"
2222
"hash"
23-
"runtime"
24-
25-
"github.com/klauspost/cpuid/v2"
2623
)
2724

2825
// Size - The size of a SHA256 checksum in bytes.
@@ -68,42 +65,34 @@ func (d *digest) Reset() {
6865
type blockfuncType int
6966

7067
const (
71-
blockfuncGeneric blockfuncType = iota
72-
blockfuncSha blockfuncType = iota
73-
blockfuncArm blockfuncType = iota
68+
blockfuncStdlib blockfuncType = iota
69+
blockfuncIntelSha
70+
blockfuncArmSha2
71+
blockfuncForceGeneric = -1
7472
)
7573

7674
var blockfunc blockfuncType
7775

7876
func init() {
79-
blockfunc = blockfuncGeneric
8077
switch {
81-
case hasSHAExtensions():
82-
blockfunc = blockfuncSha
78+
case hasIntelSha:
79+
blockfunc = blockfuncIntelSha
8380
case hasArmSha2():
84-
blockfunc = blockfuncArm
85-
default:
86-
blockfunc = blockfuncGeneric
81+
blockfunc = blockfuncArmSha2
8782
}
8883
}
8984

90-
var avx512 = cpuid.CPU.Supports(cpuid.AVX512F, cpuid.AVX512DQ, cpuid.AVX512BW, cpuid.AVX512VL)
91-
92-
// hasSHAExtensions return whether the cpu supports SHA extensions.
93-
func hasSHAExtensions() bool {
94-
return cpuid.CPU.Supports(cpuid.SHA, cpuid.SSSE3, cpuid.SSE4) && runtime.GOARCH == "amd64"
95-
}
96-
9785
// New returns a new hash.Hash computing the SHA256 checksum.
9886
func New() hash.Hash {
99-
if blockfunc != blockfuncGeneric {
100-
d := new(digest)
101-
d.Reset()
102-
return d
87+
if blockfunc == blockfuncStdlib {
88+
// Fallback to the standard golang implementation
89+
// if no features were found.
90+
return sha256.New()
10391
}
104-
// Fallback to the standard golang implementation
105-
// if no features were found.
106-
return sha256.New()
92+
93+
d := new(digest)
94+
d.Reset()
95+
return d
10796
}
10897

10998
// Sum256 - single caller sha256 helper
@@ -272,11 +261,11 @@ func (d *digest) checkSum() (digest [Size]byte) {
272261
}
273262

274263
func block(dig *digest, p []byte) {
275-
if blockfunc == blockfuncSha {
276-
blockShaGo(dig, p)
277-
} else if blockfunc == blockfuncArm {
278-
blockArmGo(dig, p)
279-
} else if blockfunc == blockfuncGeneric {
264+
if blockfunc == blockfuncIntelSha {
265+
blockIntelShaGo(dig, p)
266+
} else if blockfunc == blockfuncArmSha2 {
267+
blockArmSha2Go(dig, p)
268+
} else {
280269
blockGeneric(dig, p)
281270
}
282271
}

sha256_test.go

+22-16
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ import (
5454
"fmt"
5555
"strings"
5656
"testing"
57-
58-
"github.com/klauspost/cpuid/v2"
5957
)
6058

6159
type sha256Test struct {
@@ -2217,7 +2215,7 @@ func TestGolden(t *testing.T) {
22172215
}()
22182216

22192217
if true {
2220-
blockfunc = blockfuncGeneric
2218+
blockfunc = blockfuncForceGeneric
22212219
for _, g := range golden {
22222220
s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
22232221
if Sum256([]byte(g.in)) != g.out {
@@ -2226,8 +2224,8 @@ func TestGolden(t *testing.T) {
22262224
}
22272225
}
22282226

2229-
if cpuid.CPU.Supports(cpuid.SHA, cpuid.SSSE3, cpuid.SSE4) {
2230-
blockfunc = blockfuncSha
2227+
if hasIntelSha {
2228+
blockfunc = blockfuncIntelSha
22312229
for _, g := range golden {
22322230
s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
22332231
if Sum256([]byte(g.in)) != g.out {
@@ -2237,7 +2235,7 @@ func TestGolden(t *testing.T) {
22372235
}
22382236

22392237
if hasArmSha2() {
2240-
blockfunc = blockfuncArm
2238+
blockfunc = blockfuncArmSha2
22412239
for _, g := range golden {
22422240
s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
22432241
if Sum256([]byte(g.in)) != g.out {
@@ -2269,27 +2267,34 @@ func benchmarkSize(b *testing.B, size int) {
22692267
b.ResetTimer()
22702268
for i := 0; i < b.N; i++ {
22712269
bench.Reset()
2272-
bench.Write(buf[:size])
2270+
bench.Write(buf)
22732271
bench.Sum(sum[:0])
22742272
}
22752273
}
22762274

22772275
func BenchmarkHash(b *testing.B) {
2278-
algos := []struct {
2276+
type alg struct {
22792277
n string
22802278
t blockfuncType
2281-
f bool
2282-
}{
2283-
{"SHA_", blockfuncSha, hasSHAExtensions()},
2284-
{"GEN_", blockfuncGeneric, true},
22852279
}
2280+
algos := make([]alg, 0, 2)
2281+
2282+
algos = append(algos, alg{"Generic", blockfuncForceGeneric})
2283+
if hasIntelSha {
2284+
algos = append(algos, alg{"IntelSHA", blockfuncIntelSha})
2285+
}
2286+
if hasArmSha2() {
2287+
algos = append(algos, alg{"ArmSha2", blockfuncArmSha2})
2288+
}
2289+
algos = append(algos, alg{"GoStdlib", blockfuncStdlib})
22862290

22872291
sizes := []struct {
22882292
n string
22892293
f func(*testing.B, int)
22902294
s int
22912295
}{
22922296
{"8Bytes", benchmarkSize, 1 << 3},
2297+
{"64Bytes", benchmarkSize, 1 << 6},
22932298
{"1K", benchmarkSize, 1 << 10},
22942299
{"8K", benchmarkSize, 1 << 13},
22952300
{"1M", benchmarkSize, 1 << 20},
@@ -2298,14 +2303,15 @@ func BenchmarkHash(b *testing.B) {
22982303
}
22992304

23002305
for _, a := range algos {
2301-
if a.f {
2302-
blockfuncSaved := blockfunc
2306+
func() {
2307+
orig := blockfunc
2308+
defer func() { blockfunc = orig }()
2309+
23032310
blockfunc = a.t
23042311
for _, y := range sizes {
23052312
s := a.n + "/" + y.n
23062313
b.Run(s, func(b *testing.B) { y.f(b, y.s) })
23072314
}
2308-
blockfunc = blockfuncSaved
2309-
}
2315+
}()
23102316
}
23112317
}

sha256blockAvx512_amd64.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//+build !noasm,!appengine,gc
1+
//go:build !noasm && !appengine && gc
2+
// +build !noasm,!appengine,gc
23

34
/*
45
* Minio Cloud Storage, (C) 2017 Minio, Inc.

sha256blockAvx512_amd64_test.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//+build !noasm,!appengine,gc
1+
//go:build !noasm && !appengine && gc
2+
// +build !noasm,!appengine,gc
23

34
/*
45
* Minio Cloud Storage, (C) 2017 Minio, Inc.
@@ -31,7 +32,7 @@ import (
3132

3233
func TestGoldenAVX512(t *testing.T) {
3334

34-
if !avx512 {
35+
if !hasAvx512 {
3536
t.SkipNow()
3637
return
3738
}
@@ -75,7 +76,7 @@ func initDigests() *[512]byte {
7576

7677
func testSha256Avx512(t *testing.T, offset, padding int) [16][]byte {
7778

78-
if !avx512 {
79+
if !hasAvx512 {
7980
t.SkipNow()
8081
return [16][]byte{}
8182
}
@@ -118,7 +119,7 @@ func TestAvx512_3Blocks(t *testing.T) { testSha256Avx512(t, 47, 55) }
118119

119120
func TestAvx512_MixedBlocks(t *testing.T) {
120121

121-
if !avx512 {
122+
if !hasAvx512 {
122123
t.SkipNow()
123124
return
124125
}
@@ -153,7 +154,7 @@ func TestAvx512_MixedBlocks(t *testing.T) {
153154

154155
func TestAvx512_MixedWithNilBlocks(t *testing.T) {
155156

156-
if !avx512 {
157+
if !hasAvx512 {
157158
t.SkipNow()
158159
return
159160
}
@@ -200,7 +201,7 @@ func TestAvx512_MixedWithNilBlocks(t *testing.T) {
200201

201202
func TestAvx512Server(t *testing.T) {
202203

203-
if !avx512 {
204+
if !hasAvx512 {
204205
t.SkipNow()
205206
return
206207
}
@@ -251,7 +252,7 @@ func TestAvx512Server(t *testing.T) {
251252

252253
func TestAvx512Digest(t *testing.T) {
253254

254-
if !avx512 {
255+
if !hasAvx512 {
255256
t.SkipNow()
256257
return
257258
}
@@ -295,7 +296,7 @@ func benchmarkAvx512SingleCore(h512 []hash.Hash, body []byte) {
295296

296297
func benchmarkAvx512(b *testing.B, size int) {
297298

298-
if !avx512 {
299+
if !hasAvx512 {
299300
b.SkipNow()
300301
return
301302
}
@@ -325,7 +326,7 @@ func BenchmarkAvx512_10M(b *testing.B) { benchmarkAvx512(b, 10*1024*1024) }
325326

326327
func benchmarkAvx512MultiCore(b *testing.B, size, cores int) {
327328

328-
if !avx512 {
329+
if !hasAvx512 {
329330
b.SkipNow()
330331
return
331332
}

sha256blockSha_amd64.go

-6
This file was deleted.

sha256block_amd64.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//+build !noasm,!appengine,gc
1+
//go:build !noasm && !appengine && gc
2+
// +build !noasm,!appengine,gc
23

34
/*
45
* Minio Cloud Storage, (C) 2016 Minio, Inc.
@@ -18,10 +19,13 @@
1819

1920
package sha256
2021

21-
func blockArmGo(dig *digest, p []byte) {
22-
panic("blockArmGo called unexpectedly")
22+
func blockArmSha2Go(dig *digest, p []byte) {
23+
panic("blockArmSha2Go called unexpectedly")
2324
}
2425

25-
func blockShaGo(dig *digest, p []byte) {
26-
blockSha(&dig.h, p)
26+
//go:noescape
27+
func blockIntelSha(h *[8]uint32, message []uint8)
28+
29+
func blockIntelShaGo(dig *digest, p []byte) {
30+
blockIntelSha(&dig.h, p)
2731
}

sha256blockSha_amd64.s sha256block_amd64.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ GLOBL SHUF_MASK<>(SB), RODATA|NOPTR, $16
106106
// X13 saved hash state // CDGH
107107
// X15 data shuffle mask (constant)
108108

109-
TEXT ·blockSha(SB), NOSPLIT, $0-32
109+
TEXT ·blockIntelSha(SB), NOSPLIT, $0-32
110110
MOVQ h+0(FP), DX
111111
MOVQ message_base+8(FP), SI
112112
MOVQ message_len+16(FP), DI

sha256blockSha_amd64_test.go sha256block_amd64_test.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//+build !noasm,!appengine,gc
1+
//go:build !noasm && !appengine && gc
2+
// +build !noasm,!appengine,gc
23

34
package sha256
45

@@ -20,7 +21,7 @@ func sha256hash(m []byte) (r [32]byte) {
2021
h[6] = 0x1f83d9ab
2122
h[7] = 0x5be0cd19
2223

23-
blockSha(&h, m)
24+
blockIntelSha(&h, m)
2425
l0 := len(m)
2526
l := l0 & (BlockSize - 1)
2627
m = m[l0-l:]
@@ -31,7 +32,7 @@ func sha256hash(m []byte) (r [32]byte) {
3132
k[l] = 0x80
3233

3334
if l >= 56 {
34-
blockSha(&h, k[:])
35+
blockIntelSha(&h, k[:])
3536
binary.LittleEndian.PutUint64(k[0:8], 0)
3637
binary.LittleEndian.PutUint64(k[8:16], 0)
3738
binary.LittleEndian.PutUint64(k[16:24], 0)
@@ -41,7 +42,7 @@ func sha256hash(m []byte) (r [32]byte) {
4142
binary.LittleEndian.PutUint64(k[48:56], 0)
4243
}
4344
binary.BigEndian.PutUint64(k[56:64], uint64(l0)<<3)
44-
blockSha(&h, k[:])
45+
blockIntelSha(&h, k[:])
4546

4647
binary.BigEndian.PutUint32(r[0:4], h[0])
4748
binary.BigEndian.PutUint32(r[4:8], h[1])
@@ -71,7 +72,7 @@ func TestSha0(t *testing.T) {
7172
}
7273

7374
func TestSha1(t *testing.T) {
74-
if hasSHAExtensions() && !runTestSha(sha256hash) {
75+
if hasIntelSha && !runTestSha(sha256hash) {
7576
t.Errorf("FAILED")
7677
}
7778
}

0 commit comments

Comments
 (0)