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
#include <wolfssl/ssl.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
#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;
#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
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_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,
int callAgain, int* times, int limit, int* pending)
@ -1196,8 +1243,12 @@ static int gPrintStats = 0;
typedef enum bench_stat_type {
BENCH_STAT_ASYM,
BENCH_STAT_SYM,
BENCH_STAT_IGNORE,
} 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
#define BENCH_MAX_NAME_SZ 24
#endif
@ -1216,7 +1267,6 @@ typedef enum bench_stat_type {
} bench_stats_t;
static bench_stats_t* bench_stats_head;
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,
const char* algo, int strength, const char* desc, int doAsync,
@ -1242,7 +1292,8 @@ typedef enum bench_stat_type {
if (bstat == NULL) {
/* 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) {
XMEMSET(bstat, 0, sizeof(bench_stats_t));
@ -1312,7 +1363,8 @@ typedef enum bench_stat_type {
bench_stat_type_t type;
int ret;
} 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 int gStatsCount;
@ -1324,8 +1376,29 @@ typedef enum bench_stat_type {
if (gStatsCount >= MAX_BENCH_STATS)
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->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->perfsec = perfsec;
bstat->perftype = perftype;
@ -1335,6 +1408,10 @@ typedef enum bench_stat_type {
(void)doAsync;
#ifdef WC_ENABLE_BENCH_THREADING
pthread_mutex_unlock(&bench_lock);
#endif
return bstat;
}
@ -1342,16 +1419,53 @@ typedef enum bench_stat_type {
{
int i;
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++) {
bstat = &gStats[i];
if (bstat->type == BENCH_STAT_SYM) {
printf("%-16s %8.3f %s/s\n", bstat->desc, bstat->perfsec,
base2 ? "MB" : "mB");
}
else {
else if (bstat->type == BENCH_STAT_ASYM) {
printf("%-5s %4d %-9s %.3f ops/sec\n",
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 */
@ -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);
} else {
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],
persec, blockType);
desc, BENCH_ASYNC_GET_NAME(doAsync), blocks, blockType, word[0],
total, word[1], persec, blockType);
SHOW_INTEL_CYCLES(msg, sizeof(msg), countSz);
}
printf("%s", msg);
@ -1446,7 +1560,7 @@ static void bench_stats_sym_finish(const char* desc, int doAsync, int count,
}
/* 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)ret;
@ -2321,7 +2435,7 @@ int benchmark_free(void)
{
int ret;
#ifndef HAVE_RENESAS_SYNC
#ifdef WC_ENABLE_BENCH_THREADING
if (gPrintStats || devId != INVALID_DEVID) {
bench_stats_print();
}
@ -2363,6 +2477,43 @@ int benchmark_free(void)
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 */
#ifdef HAVE_STACK_SIZE
THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args)
@ -2374,10 +2525,6 @@ int benchmark_test(void *args)
(void)args;
printf("------------------------------------------------------------------------------\n");
printf(" wolfSSL version %s\n", LIBWOLFSSL_VERSION_STRING);
printf("------------------------------------------------------------------------------\n");
#ifdef HAVE_FIPS
wolfCrypt_SetCb_fips(myFipsCb);
#endif
@ -7343,7 +7490,7 @@ static void Usage(void)
#endif
printf("%s", bench_Usage_msg1[lng_index][14]); /* option -lng */
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> */
#endif
printf("%s", bench_Usage_msg1[lng_index][17]); /* option -print */
@ -7384,6 +7531,10 @@ int main(int argc, char** argv)
benchmark_static_init();
printf("------------------------------------------------------------------------------\n");
printf(" wolfSSL version %s\n", LIBWOLFSSL_VERSION_STRING);
printf("------------------------------------------------------------------------------\n");
#ifndef MAIN_NO_ARGS
while (argc > 1) {
if (string_matches(argv[1], "-?")) {
@ -7396,13 +7547,6 @@ int main(int argc, char** argv)
Usage();
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")) {
argc--;
argv++;
@ -7457,7 +7601,7 @@ int main(int argc, char** argv)
csv_header_count = 1;
}
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING)
#ifdef WC_ENABLE_BENCH_THREADING
else if (string_matches(argv[1], "-threads")) {
argc--;
argv++;
@ -7542,11 +7686,19 @@ int main(int argc, char** argv)
}
#endif /* MAIN_NO_ARGS */
#ifdef HAVE_STACK_SIZE
ret = StackSizeCheck(NULL, benchmark_test);
#else
ret = benchmark_test(NULL);
#if defined(WC_ENABLE_BENCH_THREADING) && !defined(WOLFSSL_ASYNC_CRYPT)
if (g_threadCount > 1) {
ret = benchmark_test_threaded(NULL);
}
else
#endif
{
#ifdef HAVE_STACK_SIZE
ret = StackSizeCheck(NULL, benchmark_test);
#else
ret = benchmark_test(NULL);
#endif
}
return ret;
}