From 5046962634d83a01341585f9f96090add2396e82 Mon Sep 17 00:00:00 2001
From: Jakob Unterwurzacher
Date: Fri, 3 Sep 2021 17:40:29 +0200
Subject: speed: add bEncrypt helper, reuse dst buffer

The bEncrypt helper massively deduplicates the code,
and reusing the dst buffer gives higher performance,
and that's what gocryptfs does in normal operation via
sync.Pool.

$ benchstat old.txt new.txt
name             old time/op   new time/op    delta
StupidGCM-4       6.24µs ± 1%    4.65µs ± 0%  -25.47%  (p=0.008 n=5+5)
GoGCM-4           4.90µs ± 0%    4.10µs ± 0%  -16.44%  (p=0.008 n=5+5)
AESSIV-4          26.4µs ± 0%    25.6µs ± 0%   -2.90%  (p=0.008 n=5+5)
Xchacha-4         5.76µs ± 0%    4.91µs ± 0%  -14.79%  (p=0.008 n=5+5)
StupidXchacha-4   7.24µs ± 1%    5.48µs ± 0%  -24.33%  (p=0.008 n=5+5)

name             old speed     new speed      delta
StupidGCM-4      656MB/s ± 1%   880MB/s ± 0%  +34.15%  (p=0.008 n=5+5)
GoGCM-4          835MB/s ± 0%  1000MB/s ± 0%  +19.68%  (p=0.008 n=5+5)
AESSIV-4         155MB/s ± 0%   160MB/s ± 0%   +2.99%  (p=0.008 n=5+5)
Xchacha-4        711MB/s ± 0%   834MB/s ± 0%  +17.35%  (p=0.008 n=5+5)
StupidXchacha-4  565MB/s ± 1%   747MB/s ± 0%  +32.15%  (p=0.008 n=5+5)
---
 internal/speed/speed.go | 85 +++++++++++++++----------------------------------
 1 file changed, 25 insertions(+), 60 deletions(-)

diff --git a/internal/speed/speed.go b/internal/speed/speed.go
index d53e402..37b9daf 100644
--- a/internal/speed/speed.go
+++ b/internal/speed/speed.go
@@ -73,35 +73,36 @@ func randBytes(n int) []byte {
 	return b
 }
 
-// bStupidGCM benchmarks stupidgcm's openssl GCM
-func bStupidGCM(b *testing.B) {
-	if stupidgcm.BuiltWithoutOpenssl {
-		b.Skip("openssl has been disabled at compile-time")
-	}
-	key := randBytes(32)
+// bEncrypt benchmarks the encryption speed of cipher "c"
+func bEncrypt(b *testing.B, c cipher.AEAD) {
 	authData := randBytes(adLen)
-	iv := randBytes(16)
+	iv := randBytes(c.NonceSize())
 	in := make([]byte, blockSize)
-	b.SetBytes(int64(len(in)))
-
-	sGCM := stupidgcm.New(key, false)
+	dst := make([]byte, len(in)+len(iv)+c.Overhead())
+	copy(dst, iv)
 
+	b.SetBytes(int64(len(in)))
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
+		// Reset dst buffer
+		dst = dst[:len(iv)]
 		// Encrypt and append to nonce
-		sGCM.Seal(iv, iv, in, authData)
+		c.Seal(dst, iv, in, authData)
 	}
+
+}
+
+// bStupidGCM benchmarks stupidgcm's openssl GCM
+func bStupidGCM(b *testing.B) {
+	if stupidgcm.BuiltWithoutOpenssl {
+		b.Skip("openssl has been disabled at compile-time")
+	}
+	bEncrypt(b, stupidgcm.New(randBytes(32), false))
 }
 
 // bGoGCM benchmarks Go stdlib GCM
 func bGoGCM(b *testing.B) {
-	key := randBytes(32)
-	authData := randBytes(adLen)
-	iv := randBytes(16)
-	in := make([]byte, blockSize)
-	b.SetBytes(int64(len(in)))
-
-	gAES, err := aes.NewCipher(key)
+	gAES, err := aes.NewCipher(randBytes(32))
 	if err != nil {
 		b.Fatal(err)
 	}
@@ -109,44 +110,19 @@ func bGoGCM(b *testing.B) {
 	if err != nil {
 		b.Fatal(err)
 	}
-
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		// Encrypt and append to nonce
-		gGCM.Seal(iv, iv, in, authData)
-	}
+	bEncrypt(b, gGCM)
 }
 
 // bAESSIV benchmarks AES-SIV from github.com/jacobsa/crypto/siv
 func bAESSIV(b *testing.B) {
-	key := randBytes(64)
-	authData := randBytes(adLen)
-	iv := randBytes(16)
-	in := make([]byte, blockSize)
-	b.SetBytes(int64(len(in)))
-	gGCM := siv_aead.New(key)
-
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		// Encrypt and append to nonce
-		gGCM.Seal(iv, iv, in, authData)
-	}
+	c := siv_aead.New(randBytes(64))
+	bEncrypt(b, c)
 }
 
 // bXchacha20poly1305 benchmarks XChaCha20 from golang.org/x/crypto/chacha20poly1305
 func bXchacha20poly1305(b *testing.B) {
-	key := randBytes(32)
-	authData := randBytes(adLen)
-	iv := randBytes(chacha20poly1305.NonceSizeX)
-	in := make([]byte, blockSize)
-	b.SetBytes(int64(len(in)))
-	c, _ := chacha20poly1305.NewX(key)
-
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		// Encrypt and append to nonce
-		c.Seal(iv, iv, in, authData)
-	}
+	c, _ := chacha20poly1305.NewX(randBytes(32))
+	bEncrypt(b, c)
 }
 
 // bStupidXchacha benchmarks OpenSSL XChaCha20
@@ -154,16 +130,5 @@ func bStupidXchacha(b *testing.B) {
 	if stupidgcm.BuiltWithoutOpenssl {
 		b.Skip("openssl has been disabled at compile-time")
 	}
-	key := randBytes(32)
-	authData := randBytes(adLen)
-	iv := randBytes(chacha20poly1305.NonceSizeX)
-	in := make([]byte, blockSize)
-	b.SetBytes(int64(len(in)))
-	c := stupidgcm.NewXchacha20poly1305(key)
-
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		// Encrypt and append to nonce
-		c.Seal(iv, iv, in, authData)
-	}
+	bEncrypt(b, stupidgcm.NewXchacha20poly1305(randBytes(32)))
 }
-- 
cgit v1.2.3