Skip to content

Commit 705f775

Browse files
authored
Add Benchmarks (#11)
* Add Bash script for running benchmarks * Update `test.sh` * Update with more scripts * Update with new parallel read benchmark * Update to add missing header * Update
1 parent bb40398 commit 705f775

18 files changed

+740
-18
lines changed

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ add_example(bsp2mtx)
1212
add_example(check_equivalence)
1313
add_example(bsp-ls)
1414
add_example(benchmark_read)
15+
add_example(benchmark_read_parallel)
1516
add_example(benchmark_write)

examples/benchmark_read.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ double compute_variance(double* x, size_t n) {
4242

4343
void flush_cache() {
4444
#ifdef __APPLE__
45-
system("bash -c \"sync && sudo purge\"");
45+
int rv = system("bash -c \"sync && sudo purge\"");
4646
#elif __linux__
47-
system("bash -c \"sync\" && sudo echo 3 > /proc/sys/vm/drop_caches");
47+
int rv = system("bash -c \"sync\" && sudo sh -c \"/usr/bin/echo 3 > "
48+
"/proc/sys/vm/drop_caches\"");
4849
#else
4950
static_assert(false);
5051
#endif
52+
usleep(100000);
5153
}
5254

5355
int main(int argc, char** argv) {
@@ -60,14 +62,20 @@ int main(int argc, char** argv) {
6062

6163
printf("Opening %s\n", file_name);
6264

63-
const int num_trials = 1;
65+
const int num_trials = 10;
6466

6567
double durations[num_trials];
6668

6769
size_t nbytes = 0;
6870

6971
// To flush the filesystem cache before each trial, change to `true`.
70-
bool cold_cache = false;
72+
bool cold_cache = true;
73+
74+
// If running warm cache experiments, read once to warm cache.
75+
if (!cold_cache) {
76+
bsp_matrix_t mat = bsp_read_matrix(file_name, NULL);
77+
bsp_destroy_matrix_t(mat);
78+
}
7179

7280
for (size_t i = 0; i < num_trials; i++) {
7381
if (cold_cache) {
@@ -79,6 +87,10 @@ int main(int argc, char** argv) {
7987
durations[i] = end - begin;
8088
nbytes = bsp_matrix_nbytes(mat);
8189
bsp_destroy_matrix_t(mat);
90+
91+
double gbytes = ((double) nbytes) / 1024 / 1024 / 1024;
92+
double gbytes_s = gbytes / durations[i];
93+
printf("FORPARSER: %s,%lf,%lf\n", file_name, durations[i], gbytes_s);
8294
}
8395

8496
printf("[");
@@ -117,7 +129,5 @@ int main(int argc, char** argv) {
117129
}
118130
printf("]\n");
119131

120-
printf("FORPARSER: %s,%lf,%lf\n", file_name, median_time, gbytes_s);
121-
122132
return 0;
123133
}

examples/benchmark_read_parallel.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#include <binsparse/binsparse.h>
2+
#include <stdlib.h>
3+
#include <time.h>
4+
5+
double gettime() {
6+
struct timespec time;
7+
clock_gettime(CLOCK_MONOTONIC, &time);
8+
return ((double) time.tv_sec) + ((double) 1e-9) * time.tv_nsec;
9+
}
10+
11+
int compar(const void* a, const void* b) {
12+
double x = *((const double*) a);
13+
double y = *((const double*) b);
14+
15+
double diff = x - y;
16+
17+
if (diff > 0) {
18+
return 1;
19+
} else if (diff < 0) {
20+
return -1;
21+
} else {
22+
return 0;
23+
}
24+
}
25+
26+
double compute_variance(double* x, size_t n) {
27+
double sum = 0;
28+
29+
for (size_t i = 0; i < n; i++) {
30+
sum += x[i];
31+
}
32+
33+
double mean = sum / n;
34+
35+
double sum_of_squares = 0;
36+
for (size_t i = 0; i < n; i++) {
37+
sum_of_squares += (x[i] - mean) * (x[i] - mean);
38+
}
39+
40+
return sum_of_squares / (n - 1);
41+
}
42+
43+
void flush_cache() {
44+
#ifdef __APPLE__
45+
int rv = system("bash -c \"sync && sudo purge\"");
46+
#elif __linux__
47+
int rv = system("bash -c \"sync\" && sudo sh -c \"/usr/bin/echo 3 > "
48+
"/proc/sys/vm/drop_caches\"");
49+
#else
50+
static_assert(false);
51+
#endif
52+
usleep(100000);
53+
}
54+
55+
int main(int argc, char** argv) {
56+
if (argc < 2) {
57+
fprintf(stderr, "usage: ./benchmark_read [file_name.h5]\n");
58+
return 1;
59+
}
60+
61+
char* file_name = argv[1];
62+
63+
printf("Opening %s\n", file_name);
64+
65+
const int num_trials = 2;
66+
67+
int num_threads = 6;
68+
69+
double durations[num_trials];
70+
71+
size_t nbytes = 0;
72+
73+
// To flush the filesystem cache before each trial, change to `true`.
74+
bool cold_cache = true;
75+
76+
// If running warm cache experiments, read once to warm cache.
77+
if (!cold_cache && false) {
78+
printf("Warm cache read...\n");
79+
bsp_matrix_t mat = bsp_read_matrix_parallel(file_name, NULL, num_threads);
80+
bsp_destroy_matrix_t(mat);
81+
}
82+
83+
for (size_t i = 0; i < num_trials; i++) {
84+
if (cold_cache) {
85+
flush_cache();
86+
}
87+
double begin = gettime();
88+
bsp_matrix_t mat = bsp_read_matrix_parallel(file_name, NULL, num_threads);
89+
double end = gettime();
90+
durations[i] = end - begin;
91+
nbytes = bsp_matrix_nbytes(mat);
92+
93+
bsp_destroy_matrix_t(mat);
94+
95+
double gbytes = ((double) nbytes) / 1024 / 1024 / 1024;
96+
double gbytes_s = gbytes / durations[i];
97+
printf("FORPARSER: %s,%lf,%lf\n", file_name, durations[i], gbytes_s);
98+
}
99+
100+
printf("[");
101+
for (size_t i = 0; i < num_trials; i++) {
102+
printf("%lf", durations[i]);
103+
if (i + 1 < num_trials) {
104+
printf(", ");
105+
}
106+
}
107+
printf("]\n");
108+
109+
qsort(durations, num_trials, sizeof(double), compar);
110+
111+
double variance = compute_variance(durations, num_trials);
112+
113+
double median_time = durations[num_trials / 2];
114+
115+
printf("Read file in %lf seconds\n", median_time);
116+
117+
if (num_trials > 1) {
118+
printf("Variance is %lf seconds, standard devication is %lf seconds\n",
119+
variance, sqrt(variance));
120+
}
121+
122+
double gbytes = ((double) nbytes) / 1024 / 1024 / 1024;
123+
double gbytes_s = gbytes / median_time;
124+
125+
printf("Achieved %lf GiB/s\n", gbytes_s);
126+
127+
printf("[");
128+
for (size_t i = 0; i < num_trials; i++) {
129+
printf("%lf", durations[i]);
130+
if (i + 1 < num_trials) {
131+
printf(", ");
132+
}
133+
}
134+
printf("]\n");
135+
136+
return 0;
137+
}

examples/benchmark_write.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,21 @@ double compute_variance(double* x, size_t n) {
4242

4343
void flush_cache() {
4444
#ifdef __APPLE__
45-
system("bash -c \"sync && sudo purge\"");
45+
int rv = system("bash -c \"sync && sudo purge\"");
4646
#elif __linux__
47-
system("bash -c \"sync\" && sudo echo 3 > /proc/sys/vm/drop_caches");
47+
int rv = system("bash -c \"sync\" && sudo sh -c \"/usr/bin/echo 3 > "
48+
"/proc/sys/vm/drop_caches\"");
4849
#else
4950
static_assert(false);
5051
#endif
52+
usleep(100000);
5153
}
5254

5355
void flush_writes() {
5456
#ifdef __APPLE__
55-
system("bash -c \"sync\"");
57+
int rv = system("bash -c \"sync\"");
5658
#elif __linux__
57-
system("bash -c \"sync\"");
59+
int rv = system("bash -c \"sync\"");
5860
#else
5961
static_assert(false);
6062
#endif
@@ -63,7 +65,7 @@ void flush_writes() {
6365
void delete_file(const char* file_name) {
6466
char command[2048];
6567
snprintf(command, 2047, "rm %s", file_name);
66-
system(command);
68+
int rv = system(command);
6769
}
6870

6971
int main(int argc, char** argv) {
@@ -85,7 +87,7 @@ int main(int argc, char** argv) {
8587

8688
printf("Opening %s\n", file_name);
8789

88-
const int num_trials = 1;
90+
const int num_trials = 10;
8991

9092
double durations[num_trials];
9193

@@ -105,7 +107,7 @@ int main(int argc, char** argv) {
105107

106108
// To flush each write to the filesystem and include this in the timing,
107109
// change to `true`.
108-
bool flush_each_write = true;
110+
bool flush_each_write = false;
109111

110112
for (size_t i = 0; i < num_trials; i++) {
111113
if (cold_cache) {
@@ -125,6 +127,11 @@ int main(int argc, char** argv) {
125127
double end = gettime();
126128
durations[i] = end - begin;
127129

130+
double gbytes = ((double) nbytes) / 1024 / 1024 / 1024;
131+
double gbytes_s = gbytes / durations[i];
132+
133+
printf("FORPARSER: %s,%lf,%lf\n", file_name, durations[i], gbytes_s);
134+
128135
delete_file(output_filename);
129136
}
130137

@@ -164,7 +171,5 @@ int main(int argc, char** argv) {
164171
}
165172
printf("]\n");
166173

167-
printf("FORPARSER: %s,%lf,%lf\n", file_name, median_time, gbytes_s);
168-
169174
return 0;
170175
}

include/binsparse/array.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <assert.h>
4+
#include <binsparse/detail/shm_tools.h>
45
#include <binsparse/types.h>
56
#include <stdlib.h>
67
#include <string.h>
@@ -9,12 +10,15 @@ typedef struct bsp_array_t {
910
void* data;
1011
size_t size;
1112
bsp_type_t type;
13+
bool shmat_memory;
14+
bsp_shm_t shm;
1215
} bsp_array_t;
1316

1417
bsp_array_t bsp_construct_default_array_t() {
1518
bsp_array_t array;
1619
array.data = NULL;
1720
array.size = 0;
21+
array.shmat_memory = false;
1822
return array;
1923
}
2024

@@ -23,8 +27,10 @@ bsp_array_t bsp_construct_array_t(size_t size, bsp_type_t type) {
2327

2428
bsp_array_t array;
2529
array.data = malloc(byte_size);
30+
assert(array.data != NULL);
2631
array.size = size;
2732
array.type = type;
33+
array.shmat_memory = false;
2834

2935
return array;
3036
}
@@ -70,7 +76,37 @@ bsp_array_t bsp_fp_array_to_complex(bsp_array_t other) {
7076
}
7177

7278
void bsp_destroy_array_t(bsp_array_t array) {
73-
free(array.data);
79+
if (array.shmat_memory == false) {
80+
free(array.data);
81+
} else {
82+
bsp_shm_detach(array.data);
83+
}
84+
}
85+
86+
bool bsp_array_equal(bsp_array_t x, bsp_array_t y) {
87+
if (x.size != y.size) {
88+
return false;
89+
}
90+
91+
if (x.size == 0) {
92+
return true;
93+
}
94+
95+
if (x.type != y.type) {
96+
return false;
97+
}
98+
99+
uint8_t* x_data = (uint8_t*) x.data;
100+
uint8_t* y_data = (uint8_t*) y.data;
101+
for (size_t i = 0; i < x.size * bsp_type_size(x.type); i++) {
102+
if (x_data[i] != y_data[i]) {
103+
printf("Index %zu incorrect %d != %d\n", i, (int) x_data[i],
104+
(int) y_data[i]);
105+
fflush(stdout);
106+
return false;
107+
}
108+
}
109+
return true;
74110
}
75111

76112
#ifndef __cplusplus
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#pragma once
2+
3+
#include <stddef.h>
4+
#include <stdio.h>
5+
#include <sys/ipc.h>
6+
#include <sys/shm.h>
7+
#include <sys/stat.h>
8+
#include <sys/types.h>
9+
#include <sys/wait.h>
10+
11+
typedef struct {
12+
int id;
13+
size_t size;
14+
} bsp_shm_t;
15+
16+
bsp_shm_t bsp_shm_new(size_t size) {
17+
bsp_shm_t shm;
18+
shm.size = size;
19+
20+
if ((shm.id = shmget(IPC_PRIVATE, size,
21+
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) < 0) {
22+
perror("shmget");
23+
}
24+
25+
return shm;
26+
}
27+
28+
void bsp_shm_delete(bsp_shm_t shm) {
29+
shmctl(shm.id, IPC_RMID, 0);
30+
}
31+
32+
void* bsp_shm_attach(bsp_shm_t shm) {
33+
void* data;
34+
35+
if ((data = shmat(shm.id, NULL, 0)) == (void*) -1) {
36+
perror("write");
37+
}
38+
39+
return data;
40+
}
41+
42+
void bsp_shm_detach(void* data) {
43+
shmdt(data);
44+
}

0 commit comments

Comments
 (0)