Add a --terse option
[tools.git] / perf / handshake.c
1 /*
2  * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <openssl/ssl.h>
14 #include "perflib/perflib.h"
15
16 #define NUM_HANDSHAKES_PER_THREAD         1000
17
18 int err = 0;
19
20 static SSL_CTX *sctx = NULL, *cctx = NULL;
21
22 OSSL_TIME *times;
23
24 static void do_handshake(size_t num)
25 {
26     SSL *clientssl = NULL, *serverssl = NULL;
27     int ret = 1;
28     int i;
29     OSSL_TIME start, end;
30
31     start = ossl_time_now();
32
33     for (i = 0; i < NUM_HANDSHAKES_PER_THREAD; i++) {
34         ret = perflib_create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
35                                          NULL, NULL);
36         ret &= perflib_create_ssl_connection(serverssl, clientssl,
37                                              SSL_ERROR_NONE);
38         perflib_shutdown_ssl_connection(serverssl, clientssl);
39         serverssl = clientssl = NULL;
40     }
41
42     end = ossl_time_now();
43     times[num] = ossl_time_subtract(end, start);
44
45     if (!ret)
46         err = 1;
47 }
48
49 int main(int argc, char *argv[])
50 {
51     int threadcount;
52     double persec;
53     OSSL_TIME duration, av;
54     uint64_t us;
55     double avcalltime;
56     char *cert;
57     char *privkey;
58     int ret = EXIT_FAILURE;
59     int i;
60     int argnext;
61     int terse = 0;
62
63     if ((argc != 3 && argc != 4)
64             || (argc == 4 && strcmp("--terse", argv[1]) != 0)) {
65         printf("Usage: handshake [--terse] certsdir threadcount\n");
66         return EXIT_FAILURE;
67     }
68
69     if (argc == 4) {
70         terse = 1;
71         argnext = 2;
72     } else {
73         argnext = 1;
74     }
75
76     cert = perflib_mk_file_path(argv[argnext], "servercert.pem");
77     privkey = perflib_mk_file_path(argv[argnext], "serverkey.pem");
78     if (cert == NULL || privkey == NULL) {
79         printf("Failed to allocate cert/privkey\n");
80         goto err;
81     }
82
83     threadcount = atoi(argv[++argnext]);
84     if (threadcount < 1) {
85         printf("threadcount must be > 0\n");
86         goto err;
87     }
88
89     times = OPENSSL_malloc(sizeof(OSSL_TIME) * threadcount);
90     if (times == NULL) {
91         printf("Failed to create times array\n");
92         goto err;
93     }
94
95     if (!perflib_create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(),
96                                      0, 0, &sctx, &cctx, cert, privkey)) {
97         printf("Failed to create SSL_CTX pair\n");
98         goto err;
99     }
100
101     if (!perflib_run_multi_thread_test(do_handshake, threadcount, &duration)) {
102         printf("Failed to run the test\n");
103         goto err;
104     }
105
106     if (err) {
107         printf("Error during test\n");
108         goto err;
109     }
110
111     av = times[0];
112     for (i = 1; i < threadcount; i++)
113         av = ossl_time_add(av, times[i]);
114     av = ossl_time_divide(av, NUM_HANDSHAKES_PER_THREAD * threadcount);
115
116     persec = ((NUM_HANDSHAKES_PER_THREAD * threadcount * OSSL_TIME_SECOND)
117              / (double)ossl_time2ticks(duration));
118
119     if (terse) {
120         printf("%ld\n", ossl_time2us(av));
121         printf("%lf\n", persec);
122     } else {
123         printf("Average time per handshake: %ldus\n", ossl_time2us(av));
124         printf("Handshakes per second: %lf\n", persec);
125     }
126
127     ret = EXIT_SUCCESS;
128  err:
129     OPENSSL_free(cert);
130     OPENSSL_free(privkey);
131     OPENSSL_free(times);
132     SSL_CTX_free(sctx);
133     SSL_CTX_free(cctx);
134     return ret;
135 }