Skip to content

Commit dc8439b

Browse files
committed
adding query
1 parent cb53fbe commit dc8439b

File tree

4 files changed

+192
-4
lines changed

4 files changed

+192
-4
lines changed

Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
all: unit bench
1+
all: unit bench query
22

33
unit : tests/unit.c include/xorfilter.h include/binaryfusefilter.h
4-
${CC} -std=c99 -g -O2 -fsanitize=address,leak,undefined -o unit tests/unit.c -lm -Iinclude -Wall -Wextra -Wshadow -Wcast-qual
4+
${CC} -std=c99 -g -O2 -fsanitize=address -o unit tests/unit.c -lm -Iinclude -Wall -Wextra -Wshadow -Wcast-qual
55

66
ab : tests/a.c tests/b.c
77
${CC} -std=c99 -o c tests/a.c tests/b.c -lm -Iinclude -Wall -Wextra -Wshadow -Wcast-qual -Wconversion -Wsign-conversion
88

99
bench : benchmarks/bench.c include/xorfilter.h include/binaryfusefilter.h
1010
${CC} -std=c99 -O3 -o bench benchmarks/bench.c -lm -Iinclude -Wall -Wextra -Wshadow -Wcast-qual -Wconversion -Wsign-conversion
1111

12+
query : benchmarks/query.c include/xorfilter.h include/binaryfusefilter.h
13+
${CC} -std=c99 -O3 -o query benchmarks/query.c -lm -Iinclude -Wall -Wextra -Wshadow -Wcast-qual -Wconversion -Wsign-conversion
14+
1215
test: unit ab
1316
ASAN_OPTIONS='halt_on_error=1:abort_on_error=1:print_summary=1' \
1417
UBSAN_OPTIONS='halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' \
1518
./unit
1619

1720
clean:
18-
rm -f unit bench
21+
rm -f unit bench query

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,24 @@ It took 0.358220 seconds to build an index over 10000000 values.
184184
...
185185
```
186186

187+
Query benchmark
188+
```
189+
To run the new query benchmark (builds filters of 1,000,000 even keys and issues 1,000,000 queries to measure throughput):
190+
191+
$ make query
192+
$ ./query
193+
```
194+
195+
Sample output (shows queries/sec and nanoseconds per query):
196+
197+
```
198+
Running binary_fuse8 query benchmark
199+
binary_fuse8: 1000000 queries in 0.123456 s => 8103726.000000 q/s, 123.456000 ns/q, found=500000
200+
Running xor8 query benchmark
201+
xor8: 1000000 queries in 0.098765 s => 10123456.000000 q/s, 98.765000 ns/q, found=500000
202+
...
203+
```
204+
187205
## Policy regarding static analysis
188206

189207
We always encourage bug reports and bug fixes.

benchmarks/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ add_executable(bench bench.c)
22
target_link_libraries(bench PUBLIC xor_singleheader)
33

44
add_executable(spaceusage spaceusage.c)
5-
target_link_libraries(spaceusage PUBLIC xor_singleheader)
5+
target_link_libraries(spaceusage PUBLIC xor_singleheader)
6+
7+
add_executable(query query.c)
8+
target_link_libraries(query PUBLIC xor_singleheader)

benchmarks/query.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#include "binaryfusefilter.h"
2+
#include "xorfilter.h"
3+
#include <assert.h>
4+
#include <time.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
8+
#define N 1000000UL
9+
#define Q N
10+
11+
static double time_seconds() {
12+
return (double)clock() / (double)CLOCKS_PER_SEC;
13+
}
14+
15+
static void run_binaryfuse8() {
16+
printf("\nRunning binary_fuse8 query benchmark\n");
17+
binary_fuse8_t filter;
18+
if (!binary_fuse8_allocate((uint32_t)N, &filter)) {
19+
fprintf(stderr, "binary_fuse8_allocate failed\n");
20+
return;
21+
}
22+
uint64_t *keys = (uint64_t *)malloc(sizeof(uint64_t) * N);
23+
for (size_t i = 0; i < N; i++) keys[i] = (uint64_t)i * 2ULL; // even numbers
24+
if (!binary_fuse8_populate(keys, (uint32_t)N, &filter)) {
25+
fprintf(stderr, "binary_fuse8_populate failed\n");
26+
binary_fuse8_free(&filter);
27+
free(keys);
28+
return;
29+
}
30+
31+
// warm up
32+
for (size_t i = 0; i < 1000; i++) binary_fuse8_contain(keys[i], &filter);
33+
34+
size_t found = 0;
35+
double t0 = time_seconds();
36+
for (size_t i = 0; i < Q; i++) {
37+
if (binary_fuse8_contain((uint64_t)i, &filter)) found++;
38+
}
39+
double t1 = time_seconds();
40+
double secs = t1 - t0;
41+
double qps = (double)Q / secs;
42+
double ns_per_q = (secs * 1e9) / (double)Q;
43+
printf("binary_fuse8: %zu queries in %f s => %f q/s, %f ns/q, found=%zu\n",
44+
(size_t)Q, secs, qps, ns_per_q, found);
45+
46+
binary_fuse8_free(&filter);
47+
free(keys);
48+
}
49+
50+
static void run_xor8() {
51+
printf("\nRunning xor8 query benchmark\n");
52+
xor8_t filter;
53+
if (!xor8_allocate((uint32_t)N, &filter)) {
54+
fprintf(stderr, "xor8_allocate failed\n");
55+
return;
56+
}
57+
uint64_t *keys = (uint64_t *)malloc(sizeof(uint64_t) * N);
58+
for (size_t i = 0; i < N; i++) keys[i] = (uint64_t)i * 2ULL; // even numbers
59+
if (!xor8_populate(keys, (uint32_t)N, &filter)) {
60+
fprintf(stderr, "xor8_populate failed\n");
61+
xor8_free(&filter);
62+
free(keys);
63+
return;
64+
}
65+
66+
for (size_t i = 0; i < 1000; i++) xor8_contain(keys[i], &filter);
67+
68+
size_t found = 0;
69+
double t0 = time_seconds();
70+
for (size_t i = 0; i < Q; i++) {
71+
if (xor8_contain((uint64_t)i, &filter)) found++;
72+
}
73+
double t1 = time_seconds();
74+
double secs = t1 - t0;
75+
{
76+
double qps = (double)Q / secs;
77+
double ns_per_q = (secs * 1e9) / (double)Q;
78+
printf("xor8: %zu queries in %f s => %f q/s, %f ns/q, found=%zu\n",
79+
(size_t)Q, secs, qps, ns_per_q, found);
80+
}
81+
82+
xor8_free(&filter);
83+
free(keys);
84+
}
85+
86+
static void run_binaryfuse16() {
87+
printf("\nRunning binary_fuse16 query benchmark\n");
88+
binary_fuse16_t filter;
89+
if (!binary_fuse16_allocate((uint32_t)N, &filter)) {
90+
fprintf(stderr, "binary_fuse16_allocate failed\n");
91+
return;
92+
}
93+
uint64_t *keys = (uint64_t *)malloc(sizeof(uint64_t) * N);
94+
for (size_t i = 0; i < N; i++) keys[i] = (uint64_t)i * 2ULL; // even numbers
95+
if (!binary_fuse16_populate(keys, (uint32_t)N, &filter)) {
96+
fprintf(stderr, "binary_fuse16_populate failed\n");
97+
binary_fuse16_free(&filter);
98+
free(keys);
99+
return;
100+
}
101+
102+
for (size_t i = 0; i < 1000; i++) binary_fuse16_contain(keys[i], &filter);
103+
104+
size_t found = 0;
105+
double t0 = time_seconds();
106+
for (size_t i = 0; i < Q; i++) {
107+
if (binary_fuse16_contain((uint64_t)i, &filter)) found++;
108+
}
109+
double t1 = time_seconds();
110+
double secs = t1 - t0;
111+
{
112+
double qps = (double)Q / secs;
113+
double ns_per_q = (secs * 1e9) / (double)Q;
114+
printf("binary_fuse16: %zu queries in %f s => %f q/s, %f ns/q, found=%zu\n",
115+
(size_t)Q, secs, qps, ns_per_q, found);
116+
}
117+
118+
binary_fuse16_free(&filter);
119+
free(keys);
120+
}
121+
122+
static void run_xor16() {
123+
printf("\nRunning xor16 query benchmark\n");
124+
xor16_t filter;
125+
if (!xor16_allocate((uint32_t)N, &filter)) {
126+
fprintf(stderr, "xor16_allocate failed\n");
127+
return;
128+
}
129+
uint64_t *keys = (uint64_t *)malloc(sizeof(uint64_t) * N);
130+
for (size_t i = 0; i < N; i++) keys[i] = (uint64_t)i * 2ULL; // even numbers
131+
if (!xor16_populate(keys, (uint32_t)N, &filter)) {
132+
fprintf(stderr, "xor16_populate failed\n");
133+
xor16_free(&filter);
134+
free(keys);
135+
return;
136+
}
137+
138+
for (size_t i = 0; i < 1000; i++) xor16_contain(keys[i], &filter);
139+
140+
size_t found = 0;
141+
double t0 = time_seconds();
142+
for (size_t i = 0; i < Q; i++) {
143+
if (xor16_contain((uint64_t)i, &filter)) found++;
144+
}
145+
double t1 = time_seconds();
146+
double secs = t1 - t0;
147+
{
148+
double qps = (double)Q / secs;
149+
double ns_per_q = (secs * 1e9) / (double)Q;
150+
printf("xor16: %zu queries in %f s => %f q/s, %f ns/q, found=%zu\n",
151+
(size_t)Q, secs, qps, ns_per_q, found);
152+
}
153+
154+
xor16_free(&filter);
155+
free(keys);
156+
}
157+
158+
int main() {
159+
run_binaryfuse8();
160+
run_xor8();
161+
run_binaryfuse16();
162+
run_xor16();
163+
return 0;
164+
}

0 commit comments

Comments
 (0)