Skip to content

Commit 589b52a

Browse files
committed
Adding benchmark
1 parent 8082018 commit 589b52a

3 files changed

Lines changed: 144 additions & 2 deletions

File tree

makefile renamed to Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,20 @@ HEADERS=include/clhash.h
1212

1313
OBJECTS= clhash.o
1414

15-
all: $(OBJECTS) unit
15+
all: $(OBJECTS) unit benchmark example
1616

1717
unit : ./tests/unit.c $(HEADERS) $(OBJECTS)
1818
$(CC) $(CFLAGS) -o unit ./tests/unit.c -Iinclude $(OBJECTS)
1919

2020
example : ./example.c $(HEADERS) $(OBJECTS)
2121
$(CC) $(CFLAGS) -o example example.c -Iinclude $(OBJECTS)
2222

23+
benchmark :./benchmarks/benchmark.c $(HEADERS) $(OBJECTS)
24+
$(CC) $(CFLAGS) -o benchmark ./benchmarks/benchmark.c -Iinclude $(OBJECTS)
25+
26+
2327
clhash.o: ./src/clhash.c $(HEADERS)
2428
$(CC) $(CFLAGS) -c ./src/clhash.c -Iinclude
2529

2630
clean:
27-
rm -f $(OBJECTS) unit example
31+
rm -f $(OBJECTS) unit example benchmark

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,10 @@ int main() {
5858
}
5959

6060
``
61+
62+
## Simple benchmark
63+
64+
```bash
65+
make
66+
./benchmark
67+
```

benchmarks/benchmark.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include <stdint.h>
2+
#include <stdio.h>
3+
#include <stddef.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
#include <assert.h>
7+
#include <stdbool.h>
8+
#include <stdint.h>
9+
#include "clhash.h"
10+
11+
12+
13+
#define RDTSC_START(cycles) \
14+
do { \
15+
uint32_t cyc_high, cyc_low; \
16+
__asm volatile("cpuid\n" \
17+
"rdtsc\n" \
18+
"mov %%edx, %0\n" \
19+
"mov %%eax, %1" : \
20+
"=r" (cyc_high), \
21+
"=r"(cyc_low) : \
22+
: /* no read only */ \
23+
"%rax", "%rbx", "%rcx", "%rdx" /* clobbers */ \
24+
); \
25+
(cycles) = ((uint64_t)cyc_high << 32) | cyc_low; \
26+
} while (0)
27+
28+
#define RDTSC_STOP(cycles) \
29+
do { \
30+
uint32_t cyc_high, cyc_low; \
31+
__asm volatile("rdtscp\n" \
32+
"mov %%edx, %0\n" \
33+
"mov %%eax, %1\n" \
34+
"cpuid" : \
35+
"=r"(cyc_high), \
36+
"=r"(cyc_low) : \
37+
/* no read only registers */ : \
38+
"%rax", "%rbx", "%rcx", "%rdx" /* clobbers */ \
39+
); \
40+
(cycles) = ((uint64_t)cyc_high << 32) | cyc_low; \
41+
} while (0)
42+
43+
static __attribute__ ((noinline))
44+
uint64_t rdtsc_overhead_func(uint64_t dummy) {
45+
return dummy;
46+
}
47+
48+
uint64_t global_rdtsc_overhead = (uint64_t) UINT64_MAX;
49+
50+
#define RDTSC_SET_OVERHEAD(test, repeat) \
51+
do { \
52+
uint64_t cycles_start, cycles_final, cycles_diff; \
53+
uint64_t min_diff = UINT64_MAX; \
54+
for (int i = 0; i < repeat; i++) { \
55+
__asm volatile("" ::: /* pretend to clobber */ "memory"); \
56+
RDTSC_START(cycles_start); \
57+
test; \
58+
RDTSC_STOP(cycles_final); \
59+
cycles_diff = (cycles_final - cycles_start); \
60+
if (cycles_diff < min_diff) min_diff = cycles_diff; \
61+
} \
62+
global_rdtsc_overhead = min_diff; \
63+
} while (0) \
64+
65+
66+
/*
67+
* Prints the best number of operations per cycle where
68+
* test is the function call, answer is the expected answer generated by
69+
* test, repeat is the number of times we should repeat and size is the
70+
* number of operations represented by test.
71+
*/
72+
#define BEST_TIME(test, expected, pre, repeat, size, verbose) \
73+
do { \
74+
if (global_rdtsc_overhead == UINT64_MAX) { \
75+
RDTSC_SET_OVERHEAD(rdtsc_overhead_func(1), repeat); \
76+
} \
77+
if(verbose) printf("%-60s\t: ", #test); \
78+
fflush(NULL); \
79+
uint64_t cycles_start, cycles_final, cycles_diff; \
80+
uint64_t min_diff = (uint64_t)-1; \
81+
uint64_t sum_diff = 0; \
82+
for (int i = 0; i < repeat; i++) { \
83+
pre; \
84+
__asm volatile("" ::: /* pretend to clobber */ "memory"); \
85+
RDTSC_START(cycles_start); \
86+
if(test != expected) {printf("not expected (%d , %d )",(int)test,(int)expected);break;} \
87+
RDTSC_STOP(cycles_final); \
88+
cycles_diff = (cycles_final - cycles_start - global_rdtsc_overhead); \
89+
if (cycles_diff < min_diff) min_diff = cycles_diff; \
90+
sum_diff += cycles_diff; \
91+
} \
92+
uint64_t S = size; \
93+
float cycle_per_op = (min_diff) / (double)S; \
94+
float avg_cycle_per_op = (sum_diff) / ((double)S * repeat); \
95+
if(verbose) printf(" %.2f cycles per operation (best) ", cycle_per_op); \
96+
if(verbose) printf("\t%.2f cycles per operation (avg) ", avg_cycle_per_op); \
97+
if(verbose) printf("\n"); \
98+
if(!verbose) printf(" %.2f ",cycle_per_op); \
99+
fflush(NULL); \
100+
} while (0)
101+
102+
// looks like java
103+
uint64_t javalikehash(char *input, size_t length) {
104+
uint64_t sum = 0;
105+
for(size_t i = 0; i < length; ++i) sum = 31 * sum + (uint64_t) input[i];
106+
return sum;
107+
}
108+
109+
110+
int main() {
111+
const int MAXN = 4096;
112+
const int repeat = 50;
113+
char * randominput = (char *) malloc(MAXN);
114+
for(int k = 0; k < MAXN; k++) randominput[k] = rand();
115+
void * random = get_random_key_for_clhash(UINT64_C(0x23a23cf5033c3c81),UINT64_C(0xb3816f6a2c68e530));
116+
printf("# for each input size in bytes, we report the number of cycles used to hash a byte\n");
117+
printf("# First number is the size in bytes\n");
118+
printf("# Second number is the number of CPU cycles per byte for clhash\n");
119+
printf("# Third number is the number of CPU cycles per byte for java-like non-random hash function\n");
120+
for(int size = 8; size < MAXN; ++size) {
121+
uint64_t hashvalue = clhash(random,randominput, size);
122+
printf("%20d\t", size);
123+
BEST_TIME(clhash(random,randominput, size), hashvalue, , repeat, size, false);
124+
uint64_t javahashvalue = javalikehash(randominput, size);
125+
printf("\t");
126+
BEST_TIME(javalikehash(randominput, size), javahashvalue, , repeat, size, false);
127+
128+
printf("\n");
129+
}
130+
131+
}

0 commit comments

Comments
 (0)