Add a performance test for PEM_read_bio_PrivateKey()

We repeatedly attempt to load an RSA Private Key and measure performance.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/tools/pull/161)
This commit is contained in:
Matt Caswell 2023-07-11 16:21:26 +01:00
parent 2e35e54163
commit 4307d538d9
4 changed files with 159 additions and 2 deletions

View File

@ -1,7 +1,7 @@
all: randbytes handshake sslnew newrawkey rsasign x509storeissuer providerdoall
all: randbytes handshake sslnew newrawkey rsasign x509storeissuer providerdoall pemread
clean:
rm libperf.a *.o randbytes handshake sslnew newrawkey rsasign x509storeissuer providerdoall
rm libperf.a *.o randbytes handshake sslnew newrawkey rsasign x509storeissuer providerdoall pemread
libperf.a: perflib/*.c perflib/*.h
gcc -I$(TARGET_OSSL_INCLUDE_PATH) -I. -c perflib/*.c
@ -27,3 +27,6 @@ x509storeissuer: x509storeissuer.c libperf.a
providerdoall: providerdoall.c libperf.a
gcc -L$(TARGET_OSSL_LIBRARY_PATH) -L. -I$(TARGET_OSSL_INCLUDE_PATH) -I. -o providerdoall providerdoall.c -lperf -lcrypto
pemread: pemread.c libperf.a
gcc -L$(TARGET_OSSL_LIBRARY_PATH) -L. -I$(TARGET_OSSL_INCLUDE_PATH) -I. -o pemread pemread.c -lperf -lcrypto

127
perf/pemread.c Normal file
View File

@ -0,0 +1,127 @@
/*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include "perflib/perflib.h"
#define NUM_CALLS_PER_BLOCK 100
#define NUM_CALL_BLOCKS_PER_THREAD 100
#define NUM_CALLS_PER_THREAD (NUM_CALLS_PER_BLOCK * NUM_CALL_BLOCKS_PER_THREAD)
int err = 0;
const char *pemdataraw[] = {
"-----BEGIN RSA PRIVATE KEY-----\n",
"MIIBOgIBAAJBAMFcGsaxxdgiuuGmCkVImy4h99CqT7jwY3pexPGcnUFtR2Fh36Bp\n",
"oncwtkZ4cAgtvd4Qs8PkxUdp6p/DlUmObdkCAwEAAQJAUR44xX6zB3eaeyvTRzms\n",
"kHADrPCmPWnr8dxsNwiDGHzrMKLN+i/HAam+97HxIKVWNDH2ba9Mf1SA8xu9dcHZ\n",
"AQIhAOHPCLxbtQFVxlnhSyxYeb7O323c3QulPNn3bhOipElpAiEA2zZpBE8ZXVnL\n",
"74QjG4zINlDfH+EOEtjJJ3RtaYDugvECIBtsQDxXytChsRgDQ1TcXdStXPcDppie\n",
"dZhm8yhRTTBZAiAZjE/U9rsIDC0ebxIAZfn3iplWh84yGB3pgUI3J5WkoQIhAInE\n",
"HTUY5WRj5riZtkyGnbm3DvF+1eMtO2lYV+OuLcfE\n",
"-----END RSA PRIVATE KEY-----\n",
NULL
};
void do_pemread(size_t num)
{
EVP_PKEY *key;
BIO *pem;
int i;
char *pemdata;
size_t len;
pemdata = perflib_glue_strings(pemdataraw, &len);
if (pemdata == NULL) {
printf("Cannot create PEM data\n");
err = 1;
return;
}
pem = BIO_new_mem_buf(pemdata, len);
if (pem == NULL) {
printf("Cannot create mem BIO\n");
err = 1;
return;
}
/*
* Technically this includes the EVP_PKEY_free() in the timing - but I
* think we can live with that
*/
for (i = 0; i < NUM_CALLS_PER_THREAD; i++) {
key = PEM_read_bio_PrivateKey(pem, NULL, NULL, NULL);
if (key == NULL) {
printf("Failed to create key: %d\n", i);
err = 1;
BIO_free(pem);
return;
}
EVP_PKEY_free(key);
BIO_reset(pem);
}
BIO_free(pem);
}
int main(int argc, char *argv[])
{
int threadcount;
OSSL_TIME duration;
uint64_t us;
double avcalltime;
int terse = 0;
int argnext;
if ((argc != 2 && argc != 3)
|| (argc == 3 && strcmp("--terse", argv[1]) != 0)) {
printf("Usage: pemread [--terse] threadcount\n");
return EXIT_FAILURE;
}
if (argc == 3) {
terse = 1;
argnext = 2;
} else {
argnext = 1;
}
threadcount = atoi(argv[argnext]);
if (threadcount < 1) {
printf("threadcount must be > 0\n");
return EXIT_FAILURE;
}
if (!perflib_run_multi_thread_test(do_pemread, threadcount, &duration)) {
printf("Failed to run the test\n");
return EXIT_FAILURE;
}
if (err) {
printf("Error during test\n");
return EXIT_FAILURE;
}
us = ossl_time2us(duration);
avcalltime = (double)us / (NUM_CALL_BLOCKS_PER_THREAD * threadcount);
if (terse)
printf("%lf\n", avcalltime);
else
printf("Average time per %d PEM_read_bio_PrivateKey() calls: %lfus\n",
NUM_CALLS_PER_BLOCK, avcalltime);
return EXIT_SUCCESS;
}

View File

@ -31,3 +31,29 @@ char *perflib_mk_file_path(const char *dir, const char *file)
return full_file;
}
/*
* Glue an array of strings together and return it as an allocated string.
* Optionally return the whole length of this string in |out_len|
*/
char *perflib_glue_strings(const char *list[], size_t *out_len)
{
size_t len = 0;
char *p, *ret;
int i;
for (i = 0; list[i] != NULL; i++)
len += strlen(list[i]);
if (out_len != NULL)
*out_len = len;
ret = p = OPENSSL_malloc(len + 1);
if (p == NULL)
return NULL;
for (i = 0; list[i] != NULL; i++)
p += strlen(strcpy(p, list[i]));
return ret;
}

View File

@ -33,6 +33,7 @@ typedef pthread_t thread_t;
int perflib_run_multi_thread_test(void (*f)(size_t), size_t threadcount,
OSSL_TIME *duration);
char *perflib_mk_file_path(const char *dir, const char *file);
char *perflib_glue_strings(const char *list[], size_t *out_len);
int perflib_create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm,
int min_proto_version, int max_proto_version,