Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
bench.c
1/* Copyright (c) 2020 tevador <tevador@gmail.com> */
2/* See LICENSE for licensing information */
3
4#include <stdio.h>
5#include <stdbool.h>
6#include <string.h>
7#include <stdlib.h>
8#include <equix.h>
9#include <test_utils.h>
10#include <hashx_thread.h>
11#include <hashx_time.h>
12
13typedef struct worker_job {
14 int id;
15 hashx_thread thread;
16 equix_ctx* ctx;
17 int64_t total_sols;
18 int start;
19 int step;
20 int end;
23
24static hashx_thread_retval worker(void* args) {
25 worker_job* job = (worker_job*)args;
26 job->total_sols = 0;
27 equix_solutions_buffer* outptr = job->output;
28 for (int seed = job->start; seed < job->end; seed += job->step) {
29 equix_result result = equix_solve(job->ctx, &seed,
30 sizeof(seed), outptr);
31 if (result == EQUIX_OK) {
32 job->total_sols += outptr->count;
33 } else if (result == EQUIX_FAIL_CHALLENGE) {
34 outptr->count = 0;
35 } else if (result == EQUIX_FAIL_COMPILE) {
36 printf("Error: not supported. Try with --interpret\n");
37 exit(1);
38 break;
39 } else {
40 printf("Error: unexpected solve failure (%d)\n", (int)result);
41 exit(1);
42 break;
43 }
44 outptr++;
45 }
46 return HASHX_THREAD_SUCCESS;
47}
48
49static void print_solution(int nonce, const equix_solution* sol) {
50 output_hex((char*)&nonce, sizeof(nonce));
51 printf(" : { ");
52 for (int idx = 0; idx < EQUIX_NUM_IDX; ++idx) {
53 printf("%#06x%s", sol->idx[idx],
54 idx != EQUIX_NUM_IDX - 1 ? ", " : "");
55 }
56 printf(" }\n");
57}
58
59static const char* result_names[] = {
60 "OK",
61 "Invalid nonce",
62 "Indices out of order",
63 "Nonzero partial sum",
64 "Nonzero final sum",
65 "HashX compiler failed",
66 "(Internal) Solver not allocated",
67 "(Internal error)"
68};
69
70static void print_help(char* executable) {
71 printf("Usage: %s [OPTIONS]\n", executable);
72 printf("Supported options:\n");
73 printf(" --help show this message\n");
74 printf(" --nonces N solve N nonces (default: N=500)\n");
75 printf(" --start S start with nonce S (default: S=0)\n");
76 printf(" --threads T use T threads (default: T=1)\n");
77 printf(" --interpret use HashX interpreter\n");
78 printf(" --hugepages use hugepages\n");
79 printf(" --sols print all solutions\n");
80}
81
82int main(int argc, char** argv) {
83 int nonces, start, threads;
84 bool interpret, huge_pages, print_sols, help;
85 read_option("--help", argc, argv, &help);
86 if (help) {
87 print_help(argv[0]);
88 return 0;
89 }
90 read_int_option("--nonces", argc, argv, &nonces, 500);
91 read_int_option("--start", argc, argv, &start, 0);
92 read_option("--interpret", argc, argv, &interpret);
93 read_option("--hugepages", argc, argv, &huge_pages);
94 read_option("--sols", argc, argv, &print_sols);
95 read_int_option("--threads", argc, argv, &threads, 1);
96 equix_ctx_flags flags = EQUIX_CTX_SOLVE;
97 if (!interpret) {
98 flags |= EQUIX_CTX_MUST_COMPILE;
99 }
100 if (huge_pages) {
101 flags |= EQUIX_CTX_HUGEPAGES;
102 }
103 worker_job* jobs = malloc(sizeof(worker_job) * threads);
104 if (jobs == NULL) {
105 printf("Error: memory allocation failure\n");
106 return 1;
107 }
108 int per_thread = (nonces + threads - 1) / threads;
109 for (int thd = 0; thd < threads; ++thd) {
110 jobs[thd].ctx = equix_alloc(flags);
111 if (jobs[thd].ctx == NULL) {
112 printf("Error: memory allocation failure\n");
113 return 1;
114 }
115 jobs[thd].id = thd;
116 jobs[thd].start = start + thd;
117 jobs[thd].step = threads;
118 jobs[thd].end = start + nonces;
119 jobs[thd].output = malloc(sizeof(equix_solutions_buffer) * per_thread);
120 if (jobs[thd].output == NULL) {
121 printf("Error: memory allocation failure\n");
122 return 1;
123 }
124 }
125 printf("Solving nonces %i-%i (interpret: %i, hugepages: %i, threads: %i) ...\n", start, start + nonces - 1, interpret, huge_pages, threads);
126 int total_sols = 0;
127 double time_start, time_end;
128 time_start = hashx_time();
129 if (threads > 1) {
130 for (int thd = 0; thd < threads; ++thd) {
131 jobs[thd].thread = hashx_thread_create(&worker, &jobs[thd]);
132 }
133 for (int thd = 0; thd < threads; ++thd) {
134 hashx_thread_join(jobs[thd].thread);
135 }
136 }
137 else {
138 worker(jobs);
139 }
140 time_end = hashx_time();
141 for (int thd = 0; thd < threads; ++thd) {
142 total_sols += jobs[thd].total_sols;
143 }
144 double elapsed = time_end - time_start;
145 printf("%f solutions/nonce\n", total_sols / (double)nonces);
146 printf("%f solutions/sec. (%i thread%s)\n", total_sols / elapsed, threads, threads > 1 ? "s" : "");
147 if (print_sols) {
148 for (int thd = 0; thd < threads; ++thd) {
149 worker_job* job = &jobs[thd];
150 equix_solutions_buffer* outptr = job->output;
151 for (int seed = job->start; seed < job->end; seed += job->step) {
152 for (int sol = 0; sol < outptr->count; ++sol) {
153 print_solution(seed, &outptr->sols[sol]);
154 }
155 outptr++;
156 }
157 }
158 }
159 time_start = hashx_time();
160 for (int thd = 0; thd < threads; ++thd) {
161 worker_job* job = &jobs[thd];
162 equix_solutions_buffer* outptr = job->output;
163 for (int seed = job->start; seed < job->end; seed += job->step) {
164 for (int sol = 0; sol < outptr->count; ++sol) {
165 equix_result result = equix_verify(job->ctx, &seed, sizeof(seed), &outptr->sols[sol]);
166 if (result != EQUIX_OK) {
167 printf("Invalid solution (%s):\n", result_names[result]);
168 print_solution(seed, &outptr->sols[sol]);
169 }
170 }
171 outptr++;
172 }
173 }
174 time_end = hashx_time();
175 printf("%f verifications/sec. (1 thread)\n", total_sols / (time_end - time_start));
176 for (int thd = 0; thd < threads; ++thd) {
177 free(jobs[thd].output);
178 }
179 free(jobs);
180 return 0;
181}
int main(int argc, char *argv[])
Definition: tor_main.c:25