Some small changes to improve computation throughput of noasm chacha20 by between 4-11%. name old time/op new time/op delta ChaCha20/64-12 142ns ± 1% 132ns ± 1% -7.09% (p=0.000 n=20+20) ChaCha20/256-12 485ns ± 1% 441ns ± 1% -9.08% (p=0.000 n=20+20) ChaCha20/10x25-12 822ns ± 1% 785ns ± 1% -4.42% (p=0.000 n=20+20) ChaCha20/4096-12 484ns ± 1% 442ns ± 1% -8.80% (p=0.000 n=20+19) ChaCha20/100x40-12 8.65µs ± 1% 8.08µs ± 1% -6.54% (p=0.000 n=19+20) ChaCha20/65536-12 118µs ± 1% 106µs ± 1% -10.04% (p=0.000 n=19+20) ChaCha20/1000x65-12 120µs ± 1% 108µs ± 0% -9.84% (p=0.000 n=19+19) name old speed new speed delta ChaCha20/64-12 450MB/s ± 1% 484MB/s ± 1% +7.61% (p=0.000 n=19+19) ChaCha20/256-12 527MB/s ± 1% 580MB/s ± 1% +10.03% (p=0.000 n=20+20) ChaCha20/10x25-12 304MB/s ± 1% 318MB/s ± 1% +4.62% (p=0.000 n=20+20) ChaCha20/4096-12 529MB/s ± 1% 580MB/s ± 1% +9.70% (p=0.000 n=19+20) ChaCha20/100x40-12 463MB/s ± 1% 495MB/s ± 1% +7.00% (p=0.000 n=19+20) ChaCha20/65536-12 556MB/s ± 1% 618MB/s ± 1% +11.16% (p=0.000 n=19+20) ChaCha20/1000x65-12 542MB/s ± 1% 602MB/s ± 0% +10.92% (p=0.000 n=19+19) Redundant bound checks on loading key and nonce as uint32s in newUnauthenticatedCipher are eliminated. In the main block loop, two changes were made: 1. Specialise the xor function to addXor, so the final block state variables don't need to be separately incremented by the initial block state before XORing with the input block. 2. Change the loop condition to be bound by len(src) >=64 and len(dst) >= 64. This eliminates all bound checks later in the load-xor-store stage. As a result, src and dst are resliced in-place after each block. Change-Id: Ic3165a556bf7cb2d71349d534cdd21d06d9a7a2c GitHub-Last-Rev: b3b1a185004c551919a8984547a5bac0283919a1 GitHub-Pull-Request: golang/crypto#131 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/228618 Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Filippo Valsorda <filippo@golang.org>
43 lines
1.2 KiB
Go
43 lines
1.2 KiB
Go
// Copyright 2018 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found src the LICENSE file.
|
|
|
|
package chacha20
|
|
|
|
import "runtime"
|
|
|
|
// Platforms that have fast unaligned 32-bit little endian accesses.
|
|
const unaligned = runtime.GOARCH == "386" ||
|
|
runtime.GOARCH == "amd64" ||
|
|
runtime.GOARCH == "arm64" ||
|
|
runtime.GOARCH == "ppc64le" ||
|
|
runtime.GOARCH == "s390x"
|
|
|
|
// addXor reads a little endian uint32 from src, XORs it with (a + b) and
|
|
// places the result in little endian byte order in dst.
|
|
func addXor(dst, src []byte, a, b uint32) {
|
|
_, _ = src[3], dst[3] // bounds check elimination hint
|
|
if unaligned {
|
|
// The compiler should optimize this code into
|
|
// 32-bit unaligned little endian loads and stores.
|
|
// TODO: delete once the compiler does a reliably
|
|
// good job with the generic code below.
|
|
// See issue #25111 for more details.
|
|
v := uint32(src[0])
|
|
v |= uint32(src[1]) << 8
|
|
v |= uint32(src[2]) << 16
|
|
v |= uint32(src[3]) << 24
|
|
v ^= a + b
|
|
dst[0] = byte(v)
|
|
dst[1] = byte(v >> 8)
|
|
dst[2] = byte(v >> 16)
|
|
dst[3] = byte(v >> 24)
|
|
} else {
|
|
a += b
|
|
dst[0] = src[0] ^ byte(a)
|
|
dst[1] = src[1] ^ byte(a>>8)
|
|
dst[2] = src[2] ^ byte(a>>16)
|
|
dst[3] = src[3] ^ byte(a>>24)
|
|
}
|
|
}
|