Merge pull request #4895 from SparkiDev/benchmark_threaded

Benchmark: support multi-threaded testing
This commit is contained in:
David Garske
2022-02-27 21:41:07 -08:00
committed by GitHub

View File

@@ -42,6 +42,52 @@
#ifdef HAVE_STACK_SIZE #ifdef HAVE_STACK_SIZE
#include <wolfssl/ssl.h> #include <wolfssl/ssl.h>
#include <wolfssl/test.h> #include <wolfssl/test.h>
#elif defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING)
#define WC_ENABLE_BENCH_THREADING
/* benchmark multi-threading - disable for FIPS self test */
#elif !defined(SINGLE_THREADED) && !defined(WC_NO_BENCH_THREADING) && \
defined(HAVE_PTHREAD) && !defined(HAVE_RENESAS_SYNC)
#define WC_ENABLE_BENCH_THREADING
#if defined(_POSIX_THREADS) && !defined(__MINGW32__)
typedef void* THREAD_RETURN;
typedef pthread_t THREAD_TYPE;
#define WOLFSSL_THREAD
#define INFINITE (-1)
#define WAIT_OBJECT_0 0L
#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) || defined(FREESCALE_MQX)
typedef unsigned int THREAD_RETURN;
typedef int THREAD_TYPE;
#define WOLFSSL_THREAD
#elif defined(WOLFSSL_TIRTOS)
typedef void THREAD_RETURN;
typedef Task_Handle THREAD_TYPE;
#ifdef HAVE_STACK_SIZE
#undef EXIT_TEST
#define EXIT_TEST(ret)
#endif
#define WOLFSSL_THREAD
#elif defined(WOLFSSL_ZEPHYR)
typedef void THREAD_RETURN;
typedef struct k_thread THREAD_TYPE;
#ifdef HAVE_STACK_SIZE
#undef EXIT_TEST
#define EXIT_TEST(ret)
#endif
#define WOLFSSL_THREAD
#elif defined(NETOS)
typedef UINT THREAD_RETURN;
typedef TX_THREAD THREAD_TYPE;
#define WOLFSSL_THREAD
#define INFINITE TX_WAIT_FOREVER
#define WAIT_OBJECT_0 TX_NO_WAIT
#else
typedef unsigned int THREAD_RETURN;
typedef intptr_t THREAD_TYPE;
#define WOLFSSL_THREAD __stdcall
#endif
#endif #endif
#ifdef USE_FLAT_BENCHMARK_H #ifdef USE_FLAT_BENCHMARK_H
@@ -928,6 +974,14 @@ static THREAD_LS_T int devId = WOLFSSL_CAAM_DEVID;
static THREAD_LS_T int devId = INVALID_DEVID; static THREAD_LS_T int devId = INVALID_DEVID;
#endif #endif
#ifdef WC_ENABLE_BENCH_THREADING
typedef struct ThreadData {
pthread_t thread_id;
} ThreadData;
static ThreadData* g_threadData;
static volatile int g_threadCount;
#endif
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
static WOLF_EVENT_QUEUE eventQueue; static WOLF_EVENT_QUEUE eventQueue;
@@ -935,13 +989,6 @@ static THREAD_LS_T int devId = INVALID_DEVID;
#define BENCH_ASYNC_GET_NAME(doAsync) (doAsync) ? "HW" : "SW" #define BENCH_ASYNC_GET_NAME(doAsync) (doAsync) ? "HW" : "SW"
#define BENCH_MAX_PENDING (WOLF_ASYNC_MAX_PENDING) #define BENCH_MAX_PENDING (WOLF_ASYNC_MAX_PENDING)
#ifndef WC_NO_ASYNC_THREADING
typedef struct ThreadData {
pthread_t thread_id;
} ThreadData;
static ThreadData* g_threadData;
static int g_threadCount;
#endif
static int bench_async_check(int* ret, WC_ASYNC_DEV* asyncDev, static int bench_async_check(int* ret, WC_ASYNC_DEV* asyncDev,
int callAgain, int* times, int limit, int* pending) int callAgain, int* times, int limit, int* pending)
@@ -1196,8 +1243,12 @@ static int gPrintStats = 0;
typedef enum bench_stat_type { typedef enum bench_stat_type {
BENCH_STAT_ASYM, BENCH_STAT_ASYM,
BENCH_STAT_SYM, BENCH_STAT_SYM,
BENCH_STAT_IGNORE,
} bench_stat_type_t; } bench_stat_type_t;
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING)
#ifdef WC_ENABLE_BENCH_THREADING
static pthread_mutex_t bench_lock = PTHREAD_MUTEX_INITIALIZER;
#ifndef BENCH_MAX_NAME_SZ #ifndef BENCH_MAX_NAME_SZ
#define BENCH_MAX_NAME_SZ 24 #define BENCH_MAX_NAME_SZ 24
#endif #endif
@@ -1216,7 +1267,6 @@ typedef enum bench_stat_type {
} bench_stats_t; } bench_stats_t;
static bench_stats_t* bench_stats_head; static bench_stats_t* bench_stats_head;
static bench_stats_t* bench_stats_tail; static bench_stats_t* bench_stats_tail;
static pthread_mutex_t bench_lock = PTHREAD_MUTEX_INITIALIZER;
static bench_stats_t* bench_stats_add(bench_stat_type_t type, static bench_stats_t* bench_stats_add(bench_stat_type_t type,
const char* algo, int strength, const char* desc, int doAsync, const char* algo, int strength, const char* desc, int doAsync,
@@ -1242,7 +1292,8 @@ typedef enum bench_stat_type {
if (bstat == NULL) { if (bstat == NULL) {
/* allocate new and put on list */ /* allocate new and put on list */
bstat = (bench_stats_t*)XMALLOC(sizeof(bench_stats_t), NULL, DYNAMIC_TYPE_INFO); bstat = (bench_stats_t*)XMALLOC(sizeof(bench_stats_t), NULL,
DYNAMIC_TYPE_INFO);
if (bstat) { if (bstat) {
XMEMSET(bstat, 0, sizeof(bench_stats_t)); XMEMSET(bstat, 0, sizeof(bench_stats_t));
@@ -1312,7 +1363,8 @@ typedef enum bench_stat_type {
bench_stat_type_t type; bench_stat_type_t type;
int ret; int ret;
} bench_stats_t; } bench_stats_t;
#define MAX_BENCH_STATS 50 /* 16 threads and 8 different operations. */
#define MAX_BENCH_STATS (16 * 8)
static bench_stats_t gStats[MAX_BENCH_STATS]; static bench_stats_t gStats[MAX_BENCH_STATS];
static int gStatsCount; static int gStatsCount;
@@ -1324,8 +1376,29 @@ typedef enum bench_stat_type {
if (gStatsCount >= MAX_BENCH_STATS) if (gStatsCount >= MAX_BENCH_STATS)
return bstat; return bstat;
#ifdef WC_ENABLE_BENCH_THREADING
/* protect bench_stats_head and bench_stats_tail access */
pthread_mutex_lock(&bench_lock);
#endif
bstat = &gStats[gStatsCount++]; bstat = &gStats[gStatsCount++];
bstat->algo = algo; bstat->algo = algo;
#ifdef WC_ENABLE_BENCH_THREADING
pthread_mutex_lock(&bench_lock);
if (g_threadCount > 1) {
int algoLen = (int)(XSTRLEN(algo) + 1);
bstat->algo = (const char* )XMALLOC(algoLen, HEAP_HINT,
DYNAMIC_TYPE_TMP_BUFFER);
if (bstat->algo == NULL) {
bstat->algo = "UNKNOWN";
type = BENCH_STAT_IGNORE;
}
else {
XSTRNCPY((char* )bstat->algo, algo, algoLen);
}
}
pthread_mutex_unlock(&bench_lock);
#endif
bstat->desc = desc; bstat->desc = desc;
bstat->perfsec = perfsec; bstat->perfsec = perfsec;
bstat->perftype = perftype; bstat->perftype = perftype;
@@ -1335,6 +1408,10 @@ typedef enum bench_stat_type {
(void)doAsync; (void)doAsync;
#ifdef WC_ENABLE_BENCH_THREADING
pthread_mutex_unlock(&bench_lock);
#endif
return bstat; return bstat;
} }
@@ -1342,16 +1419,53 @@ typedef enum bench_stat_type {
{ {
int i; int i;
bench_stats_t* bstat; bench_stats_t* bstat;
#ifdef WC_ENABLE_BENCH_THREADING
pthread_mutex_lock(&bench_lock);
if (g_threadCount > 1) {
int j;
bench_stats_t* bstat2;
/* Merge results and mark duplicates with type ignore. */
for (i=0; i<gStatsCount; i++) {
bstat = &gStats[i];
if (bstat->type == BENCH_STAT_IGNORE)
continue;
for (j=i+1; j<gStatsCount; j++) {
bstat2 = &gStats[j];
if (bstat2->type == BENCH_STAT_IGNORE)
continue;
if ((XSTRNCMP(bstat->algo, bstat2->algo,
XSTRLEN(bstat->algo)) == 0) &&
(XSTRNCMP(bstat->desc, bstat2->desc,
XSTRLEN(bstat->desc)) == 0)) {
bstat2->type = BENCH_STAT_IGNORE;
bstat->perfsec += bstat2->perfsec;
}
}
}
}
pthread_mutex_unlock(&bench_lock);
#endif
for (i=0; i<gStatsCount; i++) { for (i=0; i<gStatsCount; i++) {
bstat = &gStats[i]; bstat = &gStats[i];
if (bstat->type == BENCH_STAT_SYM) { if (bstat->type == BENCH_STAT_SYM) {
printf("%-16s %8.3f %s/s\n", bstat->desc, bstat->perfsec, printf("%-16s %8.3f %s/s\n", bstat->desc, bstat->perfsec,
base2 ? "MB" : "mB"); base2 ? "MB" : "mB");
} }
else { else if (bstat->type == BENCH_STAT_ASYM) {
printf("%-5s %4d %-9s %.3f ops/sec\n", printf("%-5s %4d %-9s %.3f ops/sec\n",
bstat->algo, bstat->strength, bstat->desc, bstat->perfsec); bstat->algo, bstat->strength, bstat->desc, bstat->perfsec);
} }
#ifdef WC_ENABLE_BENCH_THREADING
pthread_mutex_lock(&bench_lock);
if (g_threadCount > 1) {
free((void*)bstat->algo);
}
pthread_mutex_unlock(&bench_lock);
#endif
} }
} }
#endif /* WOLFSSL_ASYNC_CRYPT && !WC_NO_ASYNC_THREADING */ #endif /* WOLFSSL_ASYNC_CRYPT && !WC_NO_ASYNC_THREADING */
@@ -1434,8 +1548,8 @@ static void bench_stats_sym_finish(const char* desc, int doAsync, int count,
SHOW_INTEL_CYCLES_CSV(msg, sizeof(msg), countSz); SHOW_INTEL_CYCLES_CSV(msg, sizeof(msg), countSz);
} else { } else {
XSNPRINTF(msg, sizeof(msg), "%-16s%s %5.0f %s %s %5.3f %s, %8.3f %s/s", XSNPRINTF(msg, sizeof(msg), "%-16s%s %5.0f %s %s %5.3f %s, %8.3f %s/s",
desc, BENCH_ASYNC_GET_NAME(doAsync), blocks, blockType, word[0], total, word[1], desc, BENCH_ASYNC_GET_NAME(doAsync), blocks, blockType, word[0],
persec, blockType); total, word[1], persec, blockType);
SHOW_INTEL_CYCLES(msg, sizeof(msg), countSz); SHOW_INTEL_CYCLES(msg, sizeof(msg), countSz);
} }
printf("%s", msg); printf("%s", msg);
@@ -1446,7 +1560,7 @@ static void bench_stats_sym_finish(const char* desc, int doAsync, int count,
} }
/* Add to thread stats */ /* Add to thread stats */
bench_stats_add(BENCH_STAT_SYM, NULL, 0, desc, doAsync, persec, blockType, ret); bench_stats_add(BENCH_STAT_SYM, desc, 0, desc, doAsync, persec, blockType, ret);
(void)doAsync; (void)doAsync;
(void)ret; (void)ret;
@@ -2321,7 +2435,7 @@ int benchmark_free(void)
{ {
int ret; int ret;
#ifndef HAVE_RENESAS_SYNC #ifdef WC_ENABLE_BENCH_THREADING
if (gPrintStats || devId != INVALID_DEVID) { if (gPrintStats || devId != INVALID_DEVID) {
bench_stats_print(); bench_stats_print();
} }
@@ -2363,6 +2477,43 @@ int benchmark_free(void)
return ret; return ret;
} }
#if defined(WC_ENABLE_BENCH_THREADING) && !defined(WOLFSSL_ASYNC_CRYPT)
static THREAD_RETURN WOLFSSL_THREAD run_bench(void* args)
{
benchmark_test(args);
EXIT_TEST(0);
}
static int benchmark_test_threaded(void* args)
{
int i;
printf("Threads: %d\n", g_threadCount);
g_threadData = (ThreadData*)XMALLOC(sizeof(ThreadData) * g_threadCount,
HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (g_threadData == NULL) {
printf("Thread data alloc failed!\n");
return EXIT_FAILURE;
}
for (i = 0; i < g_threadCount; i++) {
pthread_create(&g_threadData[i].thread_id, NULL, run_bench, args);
}
for (i = 0; i < g_threadCount; i++) {
pthread_join(g_threadData[i].thread_id, 0);
}
printf("\n");
bench_stats_print();
return 0;
}
#endif
/* so embedded projects can pull in tests on their own */ /* so embedded projects can pull in tests on their own */
#ifdef HAVE_STACK_SIZE #ifdef HAVE_STACK_SIZE
THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args) THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args)
@@ -2374,10 +2525,6 @@ int benchmark_test(void *args)
(void)args; (void)args;
printf("------------------------------------------------------------------------------\n");
printf(" wolfSSL version %s\n", LIBWOLFSSL_VERSION_STRING);
printf("------------------------------------------------------------------------------\n");
#ifdef HAVE_FIPS #ifdef HAVE_FIPS
wolfCrypt_SetCb_fips(myFipsCb); wolfCrypt_SetCb_fips(myFipsCb);
#endif #endif
@@ -7343,7 +7490,7 @@ static void Usage(void)
#endif #endif
printf("%s", bench_Usage_msg1[lng_index][14]); /* option -lng */ printf("%s", bench_Usage_msg1[lng_index][14]); /* option -lng */
printf("%s", bench_Usage_msg1[lng_index][15]); /* option <num> */ printf("%s", bench_Usage_msg1[lng_index][15]); /* option <num> */
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) #ifdef WC_ENABLE_BENCH_THREADING
printf("%s", bench_Usage_msg1[lng_index][16]); /* option -threads <num> */ printf("%s", bench_Usage_msg1[lng_index][16]); /* option -threads <num> */
#endif #endif
printf("%s", bench_Usage_msg1[lng_index][17]); /* option -print */ printf("%s", bench_Usage_msg1[lng_index][17]); /* option -print */
@@ -7384,6 +7531,10 @@ int main(int argc, char** argv)
benchmark_static_init(); benchmark_static_init();
printf("------------------------------------------------------------------------------\n");
printf(" wolfSSL version %s\n", LIBWOLFSSL_VERSION_STRING);
printf("------------------------------------------------------------------------------\n");
#ifndef MAIN_NO_ARGS #ifndef MAIN_NO_ARGS
while (argc > 1) { while (argc > 1) {
if (string_matches(argv[1], "-?")) { if (string_matches(argv[1], "-?")) {
@@ -7396,13 +7547,6 @@ int main(int argc, char** argv)
Usage(); Usage();
return 0; return 0;
} }
else if (string_matches(argv[1], "-v")) {
printf("-----------------------------------------------------------"
"-------------------\n wolfSSL version %s\n-----------------"
"-----------------------------------------------------------"
"--\n", LIBWOLFSSL_VERSION_STRING);
return 0;
}
else if (string_matches(argv[1], "-lng")) { else if (string_matches(argv[1], "-lng")) {
argc--; argc--;
argv++; argv++;
@@ -7457,7 +7601,7 @@ int main(int argc, char** argv)
csv_header_count = 1; csv_header_count = 1;
} }
#endif #endif
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) #ifdef WC_ENABLE_BENCH_THREADING
else if (string_matches(argv[1], "-threads")) { else if (string_matches(argv[1], "-threads")) {
argc--; argc--;
argv++; argv++;
@@ -7542,11 +7686,19 @@ int main(int argc, char** argv)
} }
#endif /* MAIN_NO_ARGS */ #endif /* MAIN_NO_ARGS */
#ifdef HAVE_STACK_SIZE #if defined(WC_ENABLE_BENCH_THREADING) && !defined(WOLFSSL_ASYNC_CRYPT)
ret = StackSizeCheck(NULL, benchmark_test); if (g_threadCount > 1) {
#else ret = benchmark_test_threaded(NULL);
ret = benchmark_test(NULL); }
else
#endif #endif
{
#ifdef HAVE_STACK_SIZE
ret = StackSizeCheck(NULL, benchmark_test);
#else
ret = benchmark_test(NULL);
#endif
}
return ret; return ret;
} }