1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #ifndef BENCHMARK_H
17 #define BENCHMARK_H
18
19 #include <stdint.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <time.h>
23 #include <sys/time.h>
24
25 #define BENCH_TIMES(func, rc, ok, times, header) \
26 { \
27 struct timespec start, end; \
28 clock_gettime(CLOCK_REALTIME, &start); \
29 for (int i = 0; i < times; i++) { \
30 rc = func; \
31 if (rc != ok) { \
32 printf("Error: %s, ret = %08x\n", #func, rc); \
33 break; \
34 } \
35 } \
36 clock_gettime(CLOCK_REALTIME, &end); \
37 uint64_t elapsedTime = (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec); \
38 printf("%-25s, %15ld, %20d, %20.2f\n", header, elapsedTime / 1000000000, times, \
39 ((double)times * 1000000000) / elapsedTime); \
40 }
41
42 #define BENCH_SECONDS(func, rc, ok, secs, header) \
43 { \
44 struct timespec start, end; \
45 uint64_t totalTime = secs * 1000000000; \
46 uint64_t elapsedTime = 0; \
47 uint64_t cnt = 0; \
48 while (elapsedTime < totalTime) { \
49 clock_gettime(CLOCK_REALTIME, &start); \
50 rc = func; \
51 if (rc != ok) { \
52 printf("Error: %s, ret = %08x\n", #func, rc); \
53 break; \
54 } \
55 clock_gettime(CLOCK_REALTIME, &end); \
56 elapsedTime += (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec); \
57 cnt++; \
58 } \
59 printf("%-25s, %15ld, %20d, %20.2f\n", header, elapsedTime / 1000000000, cnt, \
60 ((double)times * 1000000000) / elapsedTime); \
61 }
62
63 #define BENCH_SETUP(ctx, ops) \
64 do \
65 { \
66 int32_t ret; \
67 ret = ops->newCtx(&ctx); \
68 if (ret != CRYPT_SUCCESS) { \
69 printf("Failed to create context\n"); \
70 return ret; \
71 } \
72 } \
73 while (0)
74
75 #define BENCH_TEARDOWN(ctx, ops) \
76 do { \
77 ops->freeCtx(ctx); \
78 } while (0)
79
Hex2Bin(const char * hex,uint8_t * bin,uint32_t * len)80 static inline void Hex2Bin(const char *hex, uint8_t *bin, uint32_t *len)
81 {
82 *len = strlen(hex) / 2;
83 for (uint32_t i = 0; i < *len; i++) {
84 sscanf(hex + i * 2, "%2hhx", &bin[i]);
85 }
86 }
87
88 typedef struct BenchCtx_ BenchCtx;
89 // every benchmark testcase should define "NewCtx" and "FreeCtx"
90 typedef int32_t (*NewCtx)(void **ctx);
91 typedef void (*FreeCtx)(void *ctx);
92 typedef int32_t (*KeyGen)(void *ctx, BenchCtx *bench);
93 typedef int32_t (*KeyDerive)(void *ctx, BenchCtx *bench);
94 typedef int32_t (*Enc)(void *ctx, BenchCtx *bench);
95 typedef int32_t (*Dec)(void *ctx, BenchCtx *bench);
96 typedef int32_t (*Sign)(void *ctx, BenchCtx *bench);
97 typedef int32_t (*Verify)(void *ctx, BenchCtx *bench);
98
99 typedef struct {
100 uint32_t id;
101 const char *name;
102 void *oper;
103 } Operation;
104
105 typedef struct {
106 NewCtx newCtx;
107 FreeCtx freeCtx;
108 Operation ops[];
109 } CtxOps;
110
111 #define DEFINE_OPER(id, oper) {id, #oper, oper}
112 #define DEFINE_OPS(alg) \
113 static const CtxOps alg##CtxOps = { \
114 .newCtx = alg##NewCtx, \
115 .freeCtx = alg##FreeCtx, \
116 .ops = {\
117 DEFINE_OPER(1, alg##KeyGen), \
118 DEFINE_OPER(2, alg##KeyDerive), \
119 DEFINE_OPER(4, alg##Enc), \
120 DEFINE_OPER(8, alg##Dec), \
121 DEFINE_OPER(16, alg##Sign), \
122 DEFINE_OPER(32, alg##Verify), \
123 }, \
124 }
125
126 #define KEY_GEN_ID 1U
127 #define KEY_DERIVE_ID 2U
128 #define ENC_ID 4U
129 #define DEC_ID 8U
130 #define SIGN_ID 16U
131 #define VERIFY_ID 32U
132
133 typedef struct BenchCtx_ {
134 const char *name;
135 const char *desc;
136 const CtxOps *ctxOps;
137 int32_t filteredOpsNum;
138 int32_t times;
139 int32_t seconds;
140 int32_t len;
141 } BenchCtx;
142
143 #define DEFINE_BENCH_CTX(alg) \
144 BenchCtx alg##BenchCtx = { \
145 .name = #alg, \
146 .desc = #alg " benchmark", \
147 .ctxOps = &alg##CtxOps, \
148 .filteredOpsNum = sizeof(alg##CtxOps.ops) / sizeof(alg##CtxOps.ops[0]), \
149 .times = 10000, \
150 .seconds = -1, \
151 }
152
153 #endif /* BENCHMARK_H */