1
0
mirror of https://github.com/henrydcase/nobs.git synced 2024-11-22 15:18:57 +00:00

SHAKE: Don't use function pointers

* xorIn and copyOut function pointers cause input and output data
  to be moved to heap. This degrades performance of calling code.

* This change removes usage of those function pointers. We will always
  use unaligned implementation as it's faster (but may crash on some
  systems)

* Benchmark compares generic vs unaligned xorIn and copyOut

benchmark                          old ns/op     new ns/op     delta
BenchmarkPermutationFunction-4     463           815           +76.03%
BenchmarkShake128_MTU-4            4443          8180          +84.11%
BenchmarkShake256_MTU-4            4739          9060          +91.18%
BenchmarkShake256_16x-4            71886         132629        +84.50%
BenchmarkShake256_1MiB-4           3695138       6649012       +79.94%
BenchmarkCShake128_448_16x-4       21210         24611         +16.03%
BenchmarkCShake128_1MiB-4          3009342       3396496       +12.87%
BenchmarkCShake256_448_16x-4       26034         27785         +6.73%
BenchmarkCShake256_1MiB-4          3654713       3829404       +4.78%
This commit is contained in:
Henry Case 2019-05-14 16:14:13 +01:00
parent e6439f96ab
commit 49c7e4ae43
6 changed files with 26 additions and 55 deletions

View File

@ -1,27 +0,0 @@
// Copyright 2017 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.
//+build gccgo appengine !s390x
package shake
import (
"hash"
)
// new224Asm returns an assembly implementation of SHA3-224 if available,
// otherwise it returns nil.
func new224Asm() hash.Hash { return nil }
// new256Asm returns an assembly implementation of SHA3-256 if available,
// otherwise it returns nil.
func new256Asm() hash.Hash { return nil }
// new384Asm returns an assembly implementation of SHA3-384 if available,
// otherwise it returns nil.
func new384Asm() hash.Hash { return nil }
// new512Asm returns an assembly implementation of SHA3-512 if available,
// otherwise it returns nil.
func new512Asm() hash.Hash { return nil }

View File

@ -83,7 +83,7 @@ func (d *state) permute() {
case spongeAbsorbing: case spongeAbsorbing:
// If we're absorbing, we need to xor the input into the state // If we're absorbing, we need to xor the input into the state
// before applying the permutation. // before applying the permutation.
xorIn(d, d.buf) xorInUnaligned(d, d.buf)
d.buf = d.storage[:0] d.buf = d.storage[:0]
keccakF1600(&d.a) keccakF1600(&d.a)
case spongeSqueezing: case spongeSqueezing:
@ -91,7 +91,7 @@ func (d *state) permute() {
// copying more output. // copying more output.
keccakF1600(&d.a) keccakF1600(&d.a)
d.buf = d.storage[:d.rate] d.buf = d.storage[:d.rate]
copyOut(d, d.buf) copyOutUnaligned(d, d.buf)
} }
} }
@ -119,7 +119,7 @@ func (d *state) padAndPermute(dsbyte byte) {
d.permute() d.permute()
d.state = spongeSqueezing d.state = spongeSqueezing
d.buf = d.storage[:d.rate] d.buf = d.storage[:d.rate]
copyOut(d, d.buf) copyOutUnaligned(d, d.buf)
} }
// Write absorbs more data into the hash's state. It produces an error // Write absorbs more data into the hash's state. It produces an error
@ -136,7 +136,7 @@ func (d *state) Write(p []byte) (written int, err error) {
for len(p) > 0 { for len(p) > 0 {
if len(d.buf) == 0 && len(p) >= d.rate { if len(d.buf) == 0 && len(p) >= d.rate {
// The fast path; absorb a full "rate" bytes of input and apply the permutation. // The fast path; absorb a full "rate" bytes of input and apply the permutation.
xorIn(d, p[:d.rate]) xorInUnaligned(d, p[:d.rate])
p = p[d.rate:] p = p[d.rate:]
keccakF1600(&d.a) keccakF1600(&d.a)
} else { } else {

View File

@ -22,6 +22,11 @@ import (
"testing" "testing"
) )
var (
xorIn = xorInUnaligned
copyOut = copyOutUnaligned
)
const ( const (
testString = "brekeccakkeccak koax koax" testString = "brekeccakkeccak koax koax"
katFilename = "testdata/keccakKats.json.deflate" katFilename = "testdata/keccakKats.json.deflate"
@ -68,7 +73,7 @@ func testUnalignedAndGeneric(t *testing.T, testf func(impl string)) {
xorIn, copyOut = xorInGeneric, copyOutGeneric xorIn, copyOut = xorInGeneric, copyOutGeneric
testf("generic") testf("generic")
if xorImplementationUnaligned != "generic" { if xorImplementationUnaligned != "generic" {
xorIn, copyOut = xorInUnaligned, copyOutUnaligned xorIn, copyOut = xorInGeneric, copyOutGeneric
testf("unaligned") testf("unaligned")
} }
xorIn, copyOut = xorInOrig, copyOutOrig xorIn, copyOut = xorInOrig, copyOutOrig
@ -336,7 +341,7 @@ func benchmarkShake(b *testing.B, h *CShake, size, num int) {
b.StopTimer() b.StopTimer()
h.Reset() h.Reset()
data := sequentialBytes(size) data := sequentialBytes(size)
d := make([]byte, 32) var d [32]byte
b.SetBytes(int64(size * num)) b.SetBytes(int64(size * num))
b.StartTimer() b.StartTimer()
@ -346,7 +351,7 @@ func benchmarkShake(b *testing.B, h *CShake, size, num int) {
for j := 0; j < num; j++ { for j := 0; j < num; j++ {
h.Write(data) h.Write(data)
} }
h.Read(d) h.Read(d[:])
} }
} }
@ -354,6 +359,18 @@ func BenchmarkShake128_MTU(b *testing.B) { benchmarkShake(b, NewShake128(), 135
func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) } func BenchmarkShake256_MTU(b *testing.B) { benchmarkShake(b, NewShake256(), 1350, 1) }
func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) } func BenchmarkShake256_16x(b *testing.B) { benchmarkShake(b, NewShake256(), 16, 1024) }
func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) } func BenchmarkShake256_1MiB(b *testing.B) { benchmarkShake(b, NewShake256(), 1024, 1024) }
func BenchmarkCShake128_448_16x(b *testing.B) {
benchmarkShake(b, NewCShake128([]byte("ABC"), []byte("DEF")), 448, 16)
}
func BenchmarkCShake128_1MiB(b *testing.B) {
benchmarkShake(b, NewCShake128([]byte("ABC"), []byte("DEF")), 1024, 1024)
}
func BenchmarkCShake256_448_16x(b *testing.B) {
benchmarkShake(b, NewCShake256([]byte("ABC"), []byte("DEF")), 448, 16)
}
func BenchmarkCShake256_1MiB(b *testing.B) {
benchmarkShake(b, NewCShake256([]byte("ABC"), []byte("DEF")), 1024, 1024)
}
func Example_sum() { func Example_sum() {
buf := []byte("some data to hash") buf := []byte("some data to hash")

View File

@ -1,16 +0,0 @@
// Copyright 2015 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.
// +build !amd64,!386,!ppc64le appengine
package shake
var (
xorIn = xorInGeneric
copyOut = copyOutGeneric
xorInUnaligned = xorInGeneric
copyOutUnaligned = copyOutGeneric
)
const xorImplementationUnaligned = "generic"

View File

@ -26,3 +26,5 @@ func copyOutGeneric(d *state, b []byte) {
b = b[8:] b = b[8:]
} }
} }
const xorImplementationGeneric = "generic"

View File

@ -50,9 +50,4 @@ func copyOutUnaligned(d *state, buf []byte) {
copy(buf, ab[:]) copy(buf, ab[:])
} }
var (
xorIn = xorInUnaligned
copyOut = copyOutUnaligned
)
const xorImplementationUnaligned = "unaligned" const xorImplementationUnaligned = "unaligned"