File Coverage

_rhash_timing.c
Criterion Covered Total %
statement 0 64 0.0
branch 0 32 0.0
condition n/a
subroutine n/a
pod n/a
total 0 96 0.0


line stmt bran cond sub pod time code
1             /* rhash_timing.c - functions to benchmark hash algorithms,
2             *
3             * Copyright: 2010-2012 Aleksey Kravchenko
4             *
5             * Permission is hereby granted, free of charge, to any person obtaining a
6             * copy of this software and associated documentation files (the "Software"),
7             * to deal in the Software without restriction, including without limitation
8             * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9             * and/or sell copies of the Software, and to permit persons to whom the
10             * Software is furnished to do so.
11             *
12             * This program is distributed in the hope that it will be useful, but
13             * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14             * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
15             */
16              
17             /* modifier for Windows dll */
18             #if defined(_WIN32) && defined(RHASH_EXPORTS)
19             # define RHASH_API __declspec(dllexport)
20             #endif
21              
22             #include "byte_order.h"
23             #include "rhash.h"
24             #include "rhash_timing.h"
25              
26             /* DEFINE read_tsc() if possible */
27              
28             #if (defined(CPU_IA32)) || defined(CPU_X64)
29              
30             #if defined( _MSC_VER ) /* if MS VC */
31             # include
32             # pragma intrinsic( __rdtsc )
33             # define read_tsc() __rdtsc()
34             # define HAVE_TSC
35             #elif defined( __GNUC__ ) /* if GCC */
36 0           static uint64_t read_tsc(void) {
37             unsigned long lo, hi;
38 0           __asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
39 0           return (((uint64_t)hi) << 32) + lo;
40             }
41             # define HAVE_TSC
42             #endif /* _MSC_VER, __GNUC__ */
43             #endif /* CPU_IA32, CPU_X64 */
44              
45              
46             /* TIMER FUNCTIONS */
47              
48             #ifdef _WIN32
49             #include
50             #define get_timedelta(delta) QueryPerformanceCounter((LARGE_INTEGER*)delta)
51             #else
52             #define get_timedelta(delta) gettimeofday(delta, NULL)
53             #endif
54              
55             /**
56             * Return real-value representing number of seconds
57             * stored in the given timeval structure.
58             * The function is used with timers, when printing time statistics.
59             *
60             * @deprecated This function shall be removed soon.
61             *
62             * @param delta time delta to be converted
63             * @return number of seconds
64             */
65 0           static double fsec(timedelta_t* timer)
66             {
67             #ifdef _WIN32
68             LARGE_INTEGER freq;
69             QueryPerformanceFrequency(&freq);
70             return (double)*timer / freq.QuadPart;
71             #else
72 0           return ((double)timer->tv_usec / 1000000.0) + timer->tv_sec;
73             #endif
74             }
75              
76             /**
77             * Start a timer.
78             *
79             * @deprecated This function shall be removed soon, since
80             * it is not related to the hashing library main functionality.
81             *
82             * @param timer timer to start
83             */
84 0           void rhash_timer_start(timedelta_t* timer)
85             {
86 0           get_timedelta(timer);
87 0           }
88              
89             /**
90             * Stop given timer.
91             *
92             * @deprecated This function shall be removed soon, since
93             * it is not related to the hashing library main functionality.
94             *
95             * @param timer the timer to stop
96             * @return number of seconds timed
97             */
98 0           double rhash_timer_stop(timedelta_t* timer)
99             {
100             timedelta_t end;
101 0           get_timedelta(&end);
102             #ifdef _WIN32
103             *timer = end - *timer;
104             #else
105 0           timer->tv_sec = end.tv_sec - timer->tv_sec - (end.tv_usec >= timer->tv_usec ? 0 : 1);
106 0 0         timer->tv_usec = end.tv_usec + (end.tv_usec >= timer->tv_usec ? 0 : 1000000 ) - timer->tv_usec;
107             #endif
108 0           return fsec(timer);
109             }
110              
111             #ifdef _WIN32
112             /**
113             * Set process priority and affinity to use all cpu's but the first one.
114             * This improves benchmark results on a multi-cpu systems.
115             *
116             * @deprecated This function shall be removed soon.
117             */
118             static void benchmark_cpu_init(void)
119             {
120             DWORD_PTR dwProcessMask, dwSysMask, dwDesired;
121              
122             SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
123             SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
124              
125             if ( GetProcessAffinityMask(GetCurrentProcess(), &dwProcessMask, &dwSysMask) ) {
126             dwDesired = dwSysMask & (dwProcessMask & ~1); /* remove the first processor */
127             dwDesired = (dwDesired ? dwDesired : dwSysMask & ~1);
128             if (dwDesired != 0) {
129             SetProcessAffinityMask(GetCurrentProcess(), dwDesired);
130             }
131             }
132             }
133             #endif
134              
135             /**
136             * Hash a repeated message chunk by specified hash function.
137             *
138             * @deprecated This function shall be removed soon.
139             *
140             * @param hash_id hash function identifier
141             * @param message a message chunk to hash
142             * @param msg_size message chunk size
143             * @param count number of chunks
144             * @param out computed hash
145             * @return 1 on success, 0 on error
146             */
147 0           static int hash_in_loop(unsigned hash_id, const unsigned char* message, size_t msg_size, int count, unsigned char* out)
148             {
149             int i;
150 0           struct rhash_context *context = rhash_init(hash_id);
151 0 0         if (!context) return 0;
152              
153             /* process the repeated message buffer */
154 0 0         for (i = 0; i < count; i++) rhash_update(context, message, msg_size);
155 0           rhash_final(context, out);
156 0           rhash_free(context);
157 0           return 1;
158             }
159              
160             /**
161             * Benchmark a hash algorithm.
162             *
163             * @deprecated This function shall be removed soon, since
164             * it is not related to the hashing library main functionality.
165             *
166             * @param hash_id hash algorithm identifier
167             * @param flags benchmark flags, can be RHASH_BENCHMARK_QUIET and RHASH_BENCHMARK_CPB
168             * @param output the stream to print results
169             */
170 0           void rhash_run_benchmark(unsigned hash_id, unsigned flags, FILE* output)
171             {
172             unsigned char ALIGN_ATTR(16) message[8192]; /* 8 KiB */
173             timedelta_t timer;
174             int i, j;
175             size_t sz_mb, msg_size;
176 0           double time, total_time = 0;
177 0           const int rounds = 4;
178             const char* hash_name;
179             unsigned char out[130];
180             #ifdef HAVE_TSC
181 0           double cpb = 0;
182             #endif /* HAVE_TSC */
183              
184             #ifdef _WIN32
185             benchmark_cpu_init(); /* set cpu affinity to improve test results */
186             #endif
187              
188             /* set message size for fast and slow hash functions */
189 0           msg_size = 1073741824 / 2;
190 0 0         if (hash_id & (RHASH_WHIRLPOOL | RHASH_SNEFRU128 | RHASH_SNEFRU256 | RHASH_SHA3_224 | RHASH_SHA3_256 | RHASH_SHA3_384 | RHASH_SHA3_512)) {
191 0           msg_size /= 8;
192 0 0         } else if (hash_id & (RHASH_GOST | RHASH_GOST_CRYPTOPRO | RHASH_SHA384 | RHASH_SHA512)) {
193 0           msg_size /= 2;
194             }
195 0           sz_mb = msg_size / (1 << 20); /* size in MiB */
196 0           hash_name = rhash_get_name(hash_id);
197 0 0         if (!hash_name) hash_name = ""; /* benchmarking several hashes*/
198              
199 0 0         for (i = 0; i < (int)sizeof(message); i++) message[i] = i & 0xff;
200              
201 0 0         for (j = 0; j < rounds; j++) {
202 0           rhash_timer_start(&timer);
203 0           hash_in_loop(hash_id, message, sizeof(message), (int)(msg_size / sizeof(message)), out);
204              
205 0           time = rhash_timer_stop(&timer);
206 0           total_time += time;
207              
208 0 0         if ((flags & (RHASH_BENCHMARK_QUIET | RHASH_BENCHMARK_RAW)) == 0) {
209 0           fprintf(output, "%s %u MiB calculated in %.3f sec, %.3f MBps\n", hash_name, (unsigned)sz_mb, time, (double)sz_mb / time);
210 0           fflush(output);
211             }
212             }
213              
214             #if defined(HAVE_TSC)
215             /* measure the CPU "clocks per byte" speed */
216 0 0         if (flags & RHASH_BENCHMARK_CPB) {
217 0           unsigned int c1 = -1, c2 = -1;
218             unsigned volatile long long cy0, cy1, cy2;
219 0           int msg_size = 128 * 1024;
220              
221             /* make 200 tries */
222 0 0         for (i = 0; i < 200; i++) {
223 0           cy0 = read_tsc();
224 0           hash_in_loop(hash_id, message, sizeof(message), msg_size / sizeof(message), out);
225 0           cy1 = read_tsc();
226 0           hash_in_loop(hash_id, message, sizeof(message), msg_size / sizeof(message), out);
227 0           hash_in_loop(hash_id, message, sizeof(message), msg_size / sizeof(message), out);
228 0           cy2 = read_tsc();
229              
230 0           cy2 -= cy1;
231 0           cy1 -= cy0;
232 0 0         c1 = (unsigned int)(c1 > cy1 ? cy1 : c1);
233 0 0         c2 = (unsigned int)(c2 > cy2 ? cy2 : c2);
234             }
235 0           cpb = ((c2 - c1) + 1) / (double)msg_size;
236             }
237             #endif /* HAVE_TSC */
238              
239 0 0         if (flags & RHASH_BENCHMARK_RAW) {
240             /* output result in a "raw" machine-readable format */
241 0           fprintf(output, "%s\t%u\t%.3f\t%.3f", hash_name, ((unsigned)sz_mb * rounds), total_time, (double)(sz_mb * rounds) / total_time);
242             #if defined(HAVE_TSC)
243 0 0         if (flags & RHASH_BENCHMARK_CPB) fprintf(output, "\t%.2f", cpb);
244             #endif /* HAVE_TSC */
245 0           fprintf(output, "\n");
246             } else {
247 0           fprintf(output, "%s %u MiB total in %.3f sec, %.3f MBps", hash_name, ((unsigned)sz_mb * rounds), total_time, (double)(sz_mb * rounds) / total_time);
248             #if defined(HAVE_TSC)
249 0 0         if (flags & RHASH_BENCHMARK_CPB) fprintf(output, ", CPB=%.2f", cpb);
250             #endif /* HAVE_TSC */
251 0           fprintf(output, "\n");
252             }
253 0           }