From 209e6167b53be6e6ddfa569451f531dd6d792b91 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 17 Sep 2024 09:48:49 -0700 Subject: [PATCH] Exclude cipher allocation time from benchmark For each 1 MiB of data en/decrypted, 'cryptsetup benchmark' is setting up a new AF_ALG socket, which involves 4 system calls and is included in the data en/decryption time. With high-speed ciphers (e.g. VAES optimized AES-XTS) this can measure well over 10000 AF_ALG socket setups per second. This is not representative of dm-crypt, which only allocates a cipher when the dm-crypt device is created. Therefore, allocate the AF_ALG socket once, before doing the benchmark. On AMD Ryzen 9 9950X this increases the 'cryptsetup benchmark' result of AES-256-XTS slightly, from 14000 MiB/s to 14600 MiB/s. Note that an in-kernel benchmark of the crypto API with the same block size (65536 bytes) gives 34100 MiB/s, so AF_ALG still takes more time than the en/decryption itself -- this cannot easily be addressed though. Signed-off-by: Eric Biggers --- lib/crypto_backend/cipher_check.c | 45 ++++++++++++++++--------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/lib/crypto_backend/cipher_check.c b/lib/crypto_backend/cipher_check.c index 524ffe396..a9b4eb644 100644 --- a/lib/crypto_backend/cipher_check.c +++ b/lib/crypto_backend/cipher_check.c @@ -42,43 +42,36 @@ static int time_ms(struct timespec *start, struct timespec *end, double *ms) return 0; } -static int cipher_perf_one(const char *name, const char *mode, char *buffer, size_t buffer_size, - const char *key, size_t key_size, const char *iv, size_t iv_size, int enc) +static int cipher_perf_one(struct crypt_cipher_kernel *cipher, char *buffer, size_t buffer_size, + const char *iv, size_t iv_size, int enc) { - struct crypt_cipher_kernel cipher; size_t done = 0, block = CIPHER_BLOCK_BYTES; int r; if (buffer_size < block) block = buffer_size; - r = crypt_cipher_init_kernel(&cipher, name, mode, key, key_size); - if (r < 0) - return r; - while (done < buffer_size) { if ((done + block) > buffer_size) block = buffer_size - done; if (enc) - r = crypt_cipher_encrypt_kernel(&cipher, &buffer[done], &buffer[done], + r = crypt_cipher_encrypt_kernel(cipher, &buffer[done], &buffer[done], block, iv, iv_size); else - r = crypt_cipher_decrypt_kernel(&cipher, &buffer[done], &buffer[done], + r = crypt_cipher_decrypt_kernel(cipher, &buffer[done], &buffer[done], block, iv, iv_size); if (r < 0) - break; + return r; done += block; } - crypt_cipher_destroy_kernel(&cipher); - - return r; + return 0; } -static int cipher_measure(const char *name, const char *mode, char *buffer, size_t buffer_size, - const char *key, size_t key_size, const char *iv, size_t iv_size, - int encrypt, double *ms) + +static int cipher_measure(struct crypt_cipher_kernel *cipher, char *buffer, size_t buffer_size, + const char *iv, size_t iv_size, int encrypt, double *ms) { struct timespec start, end; int r; @@ -90,7 +83,7 @@ static int cipher_measure(const char *name, const char *mode, char *buffer, size if (clock_gettime(CLOCK_MONOTONIC_RAW, &start) < 0) return -EINVAL; - r = cipher_perf_one(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, encrypt); + r = cipher_perf_one(cipher, buffer, buffer_size, iv, iv_size, encrypt); if (r < 0) return r; @@ -118,15 +111,20 @@ int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, s const char *key, size_t key_size, const char *iv, size_t iv_size, double *encryption_mbs, double *decryption_mbs) { + struct crypt_cipher_kernel cipher; double ms_enc, ms_dec, ms; int r, repeat_enc, repeat_dec; + r = crypt_cipher_init_kernel(&cipher, name, mode, key, key_size); + if (r < 0) + return r; + ms_enc = 0.0; repeat_enc = 1; while (ms_enc < 1000.0) { - r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 1, &ms); + r = cipher_measure(&cipher, buffer, buffer_size, iv, iv_size, 1, &ms); if (r < 0) - return r; + goto out; ms_enc += ms; repeat_enc++; } @@ -134,9 +132,9 @@ int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, s ms_dec = 0.0; repeat_dec = 1; while (ms_dec < 1000.0) { - r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 0, &ms); + r = cipher_measure(&cipher, buffer, buffer_size, iv, iv_size, 0, &ms); if (r < 0) - return r; + goto out; ms_dec += ms; repeat_dec++; } @@ -144,5 +142,8 @@ int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, s *encryption_mbs = speed_mbs(buffer_size * repeat_enc, ms_enc); *decryption_mbs = speed_mbs(buffer_size * repeat_dec, ms_dec); - return 0; + r = 0; +out: + crypt_cipher_destroy_kernel(&cipher); + return r; }