git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/crypto/chacha20blake3/benchmark_test.go (about)

     1  package chacha20blake3_test
     2  
     3  import (
     4  	"crypto/cipher"
     5  	"crypto/rand"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"git.sr.ht/~pingoo/stdx/crypto/bchacha20blake3"
    10  	"git.sr.ht/~pingoo/stdx/crypto/chacha20blake3"
    11  	"git.sr.ht/~pingoo/stdx/crypto/schacha20blake3"
    12  	"git.sr.ht/~pingoo/stdx/crypto/xchacha20sha256"
    13  	"golang.org/x/crypto/chacha20"
    14  	"golang.org/x/crypto/chacha20poly1305"
    15  )
    16  
    17  var (
    18  	BENCHMARKS = []int64{
    19  		64,
    20  		1000,
    21  		16_000,
    22  		64_000,
    23  		1_000_000,
    24  		10_000_000,
    25  		100_000_000,
    26  	}
    27  )
    28  
    29  // go test -benchmem -bench=. git.sr.ht/~pingoo/stdx/crypto/chacha20blake3
    30  func BenchmarkEncryptAEAD(b *testing.B) {
    31  	additionalData := randBytes(b, 100)
    32  
    33  	chaCha20Key := randBytes(b, chacha20.KeySize)
    34  	xChaCha20Nonce := randBytes(b, chacha20.NonceSizeX)
    35  	bChaCha20Nonce := randBytes(b, bchacha20blake3.NonceSize)
    36  	chaCha20Nonce := randBytes(b, chacha20blake3.NonceSize)
    37  
    38  	for _, size := range BENCHMARKS {
    39  		benchmarkEncrypt(b, size, "XChaCha20_Poly1305", newXChaCha20Poly1305Cipher(b, chaCha20Key), xChaCha20Nonce, additionalData)
    40  		benchmarkEncrypt(b, size, "ChaCha20_BLAKE3", newChaCha20Blake3Cipher(b, chaCha20Key), chaCha20Nonce, additionalData)
    41  		benchmarkEncrypt(b, size, "XChaCha20_BLAKE3", newXChaCha20Blake3Cipher(b, chaCha20Key), xChaCha20Nonce, additionalData)
    42  		benchmarkEncrypt(b, size, "BChaCha20_BLAKE3", newBChaCha20Blake3Cipher(b, chaCha20Key), bChaCha20Nonce, additionalData)
    43  		benchmarkEncrypt(b, size, "SChaCha20_BLAKE3", newSChaCha20Blake3Cipher(b, chaCha20Key), bChaCha20Nonce, additionalData)
    44  		benchmarkEncrypt(b, size, "XChaCha20_SHA256", newXChaCha20Sha256Cipher(b, chaCha20Key), xChaCha20Nonce, additionalData)
    45  	}
    46  }
    47  
    48  func BenchmarkDecryptAEAD(b *testing.B) {
    49  	additionalData := randBytes(b, 100)
    50  
    51  	chaCha20Key := randBytes(b, chacha20.KeySize)
    52  	xChaCha20Nonce := randBytes(b, chacha20.NonceSizeX)
    53  	bChaCha20Nonce := randBytes(b, bchacha20blake3.NonceSize)
    54  	chaCha20Nonce := randBytes(b, chacha20blake3.NonceSize)
    55  
    56  	for _, size := range BENCHMARKS {
    57  		benchmarkDecrypt(b, size, "XChaCha20_Poly1305", newXChaCha20Poly1305Cipher(b, chaCha20Key), xChaCha20Nonce, additionalData)
    58  		benchmarkDecrypt(b, size, "ChaCha20_BLAKE3", newChaCha20Blake3Cipher(b, chaCha20Key), chaCha20Nonce, additionalData)
    59  		benchmarkDecrypt(b, size, "XChaCha20_BLAKE3", newXChaCha20Blake3Cipher(b, chaCha20Key), xChaCha20Nonce, additionalData)
    60  		benchmarkEncrypt(b, size, "BChaCha20_BLAKE3", newBChaCha20Blake3Cipher(b, chaCha20Key), bChaCha20Nonce, additionalData)
    61  		benchmarkDecrypt(b, size, "SChaCha20_BLAKE3", newSChaCha20Blake3Cipher(b, chaCha20Key), bChaCha20Nonce, additionalData)
    62  		benchmarkDecrypt(b, size, "XChaCha20_SHA256", newXChaCha20Sha256Cipher(b, chaCha20Key), xChaCha20Nonce, additionalData)
    63  	}
    64  }
    65  
    66  func benchmarkEncrypt[C cipher.AEAD](b *testing.B, size int64, algorithm string, cipher C, nonce, additionalData []byte) {
    67  	b.Run(fmt.Sprintf("%s-%s", bytesCount(size), algorithm), func(b *testing.B) {
    68  		plaintext := randBytes(b, size)
    69  		dst := make([]byte, len(plaintext)+512)
    70  		b.ReportAllocs()
    71  		b.SetBytes(size)
    72  		b.ResetTimer()
    73  		for i := 0; i < b.N; i++ {
    74  			cipher.Seal(dst, nonce, plaintext, additionalData)
    75  		}
    76  	})
    77  }
    78  
    79  func benchmarkDecrypt[C cipher.AEAD](b *testing.B, size int64, algorithm string, cipher C, nonce, additionalData []byte) {
    80  	b.Run(fmt.Sprintf("%s-%s", bytesCount(size), algorithm), func(b *testing.B) {
    81  		b.ReportAllocs()
    82  		b.SetBytes(size)
    83  		plaintext := randBytes(b, size)
    84  		cipherText := make([]byte, len(plaintext)+512)
    85  		cipherText = cipher.Seal(cipherText, nonce, plaintext, additionalData)
    86  		dst := make([]byte, len(cipherText))
    87  		b.ResetTimer()
    88  		for i := 0; i < b.N; i++ {
    89  			cipher.Open(dst, nonce, cipherText, additionalData)
    90  		}
    91  	})
    92  }
    93  
    94  func newChaCha20Blake3Cipher(b *testing.B, key []byte) *chacha20blake3.ChaCha20Blake3 {
    95  	cipher, err := chacha20blake3.New(key)
    96  	if err != nil {
    97  		b.Error(err)
    98  	}
    99  
   100  	return cipher
   101  }
   102  
   103  func newXChaCha20Blake3Cipher(b *testing.B, key []byte) *chacha20blake3.XChaCha20Blake3 {
   104  	cipher, err := chacha20blake3.NewX(key)
   105  	if err != nil {
   106  		b.Error(err)
   107  	}
   108  
   109  	return cipher
   110  }
   111  
   112  func newBChaCha20Blake3Cipher(b *testing.B, key []byte) *bchacha20blake3.BChaCha20Blake3 {
   113  	cipher, err := bchacha20blake3.New(key)
   114  	if err != nil {
   115  		b.Error(err)
   116  	}
   117  
   118  	return cipher
   119  }
   120  
   121  func newSChaCha20Blake3Cipher(b *testing.B, key []byte) *schacha20blake3.SChaCha20Blake3 {
   122  	cipher, err := schacha20blake3.New(key)
   123  	if err != nil {
   124  		b.Error(err)
   125  	}
   126  
   127  	return cipher
   128  }
   129  
   130  func newXChaCha20Sha256Cipher(b *testing.B, key []byte) *xchacha20sha256.XChaCha20Sha256 {
   131  	cipher, err := xchacha20sha256.New(key)
   132  	if err != nil {
   133  		b.Error(err)
   134  	}
   135  
   136  	return cipher
   137  }
   138  
   139  func newXChaCha20Poly1305Cipher(b *testing.B, key []byte) cipher.AEAD {
   140  	cipher, err := chacha20poly1305.NewX(key)
   141  	if err != nil {
   142  		b.Error(err)
   143  	}
   144  
   145  	return cipher
   146  }
   147  
   148  func randBytes(b *testing.B, n int64) []byte {
   149  	buff := make([]byte, n)
   150  
   151  	_, err := rand.Read(buff)
   152  	if err != nil {
   153  		b.Error(err)
   154  	}
   155  
   156  	return buff
   157  }
   158  
   159  func bytesCount(b int64) string {
   160  	const unit = 1024
   161  	if b < unit {
   162  		return fmt.Sprintf("%dB", b)
   163  	}
   164  	div, exp := int64(unit), 0
   165  	for n := b / unit; n >= unit; n /= unit {
   166  		div *= unit
   167  		exp++
   168  	}
   169  	return fmt.Sprintf("%.0f%ciB",
   170  		float64(b)/float64(div), "KMGTPE"[exp])
   171  }