func SumCSHAKE256(N, S, data []byte, length int) []byte {
out := make([]byte, 64)
return sumCSHAKE256(out, N, S, data, length)
}
func sumCSHAKE256(out, N, S, data []byte, length int) []byte {
if len(out) < length {
out = make([]byte, length)
} else {
out = out[:length]
}
h := sha3.NewCSHAKE256(N, S)
h.Write(data)
h.Read(out)
return out
}
Currently this has 4 allocations:
- one for out (unless stack allocated),
- one for the SHAKE result of crypto/internal/fips140/sha3.newCShake,
- one for the initBlock allocation in crypto/internal/fips140/sha3.newCShake,
- one for the result of crypto/internal/fips140/sha3.bytepad.
We eliminate the SHAKE allocation by outlining the SHAKE allocation in
crypto/internal/fips140/sha3.NewCSHAKE128 and NewCSHAKE256. As
crypto/sha3.NewCSHAKE128 and NewCSHAKE256 immediately de-reference this
result, this allocation is eliminated.
We eliminate the bytepad allocation by instead writing the various
values directly with SHAKE.Write. Values passed to Write don't escape
and, with the exception of data (which is initBlock), all our Writes are
of fixed size allocations. We can't simply modify bytepad to return a
fixed size byte-slice as the length of data is not constant nor does it
have a reasonable upper bound.
We're stuck with the initBlock allocation because of the API (Reset and
the various marshallers), but we still net a substantial improvement.
benchstat output using the following benchmark:
func BenchmarkSumCSHAKE256(b *testing.B) {
N := []byte("N")
S := []byte("S")
data := []byte("testdata")
b.SetBytes(64)
for b.Loop() {
SumCSHAKE256(N, S, data, 64)
}
}
name old time/op new time/op delta
SumCSHAKE256-12 1.09µs ±20% 0.79µs ± 1% -27.41% (p=0.000 n=10+9)
name old speed new speed delta
SumCSHAKE256-12 59.8MB/s ±18% 81.0MB/s ± 1% +35.33% (p=0.000 n=10+9)
name old alloc/op new alloc/op delta
SumCSHAKE256-12 536B ± 0% 88B ± 0% -83.58% (p=0.000 n=10+10)
name old allocs/op new allocs/op delta
SumCSHAKE256-12 4.00 ± 0% 2.00 ± 0% -50.00% (p=0.000 n=10+10)
Updates #69982
Change-Id: If426ea8127c58f5ef062cf74712ec70fd26a7372
Reviewed-on: https://go-review.googlesource.com/c/go/+/636255
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Filippo Valsorda <filippo@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org>