1 /*********************************************************************
2 Copyright (C) 2021 The Blosc Developers <blosc@blosc.org>
3 https://blosc.org
4 License: BSD 3-Clause (see LICENSE.txt)
5
6 Benchmark for testing sframe vs frame.
7 For usage instructions of this benchmark, please see:
8 https://www.blosc.org/pages/synthetic-benchmarks/
9 We are collecting speeds for different machines, so the output of your
10 benchmarks and your processor specifications are welcome!
11
12 See LICENSE.txt for details about copyright and rights to use.
13 **********************************************************************/
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <blosc2.h>
19 #include <assert.h>
20 #include <inttypes.h>
21
22 #define KB 1024
23 #define MB (1024*KB)
24 #define GB (1024*MB)
25
26 #define NCHUNKS 1000 /* number of chunks */
27 #define CHUNKSIZE (200 * 1000)
28
29 int nchunks = NCHUNKS;
30 int iterations = 5;
31
32 #if defined(_WIN32) && !defined(__MINGW32__)
33 #include <time.h>
34 #include "win32/stdint-windows.h"
35 #else
36 #include <stdint.h>
37 #include <sys/time.h>
38 #endif
39
40 #if defined(_WIN32)
41 #include <malloc.h>
42
43 #endif /* defined(_WIN32) && !defined(__MINGW32__) */
44
45
test_update(blosc2_schunk * schunk_sframe,blosc2_schunk * schunk_cframe)46 void test_update(blosc2_schunk* schunk_sframe, blosc2_schunk* schunk_cframe) {
47 blosc_timestamp_t last, current;
48 double cframe_update_time, sframe_update_time;
49
50 size_t isize = CHUNKSIZE * sizeof(int32_t);
51 int32_t* data = malloc(isize);
52
53 // Random update list
54 int32_t* update_chunks = malloc(sizeof(int32_t) * iterations);
55 srand(time(NULL));
56 for (int i = 0; i < iterations; i++) {
57 update_chunks[i] = rand() % schunk_sframe->nchunks;
58 }
59
60 printf("*******************************************************\n");
61 printf("******************* Updating %d chunks ******************\n", iterations);
62 printf("*******************************************************\n");
63
64 // Update the sframe chunks
65 sframe_update_time = 0.0;
66 cframe_update_time = 0.0;
67 int32_t datasize = sizeof(int32_t) * CHUNKSIZE;
68 int32_t chunksize = sizeof(int32_t) * CHUNKSIZE + BLOSC_MAX_OVERHEAD;
69 uint8_t* chunk;
70 int csize;
71 int _nchunks;
72 for (int i = 0; i < iterations; i++) {
73 // Generate data
74 for (int j = 0; j < CHUNKSIZE; j++) {
75 data[j] = i * CHUNKSIZE;
76 }
77 chunk = malloc(chunksize);
78 csize = blosc2_compress_ctx(schunk_sframe->cctx, data, datasize, chunk, chunksize);
79 if (csize < 0) {
80 printf("ERROR: chunk cannot be compressed\n");
81 }
82 // Sframe
83 blosc_set_timestamp(¤t);
84 _nchunks = blosc2_schunk_update_chunk(schunk_sframe, update_chunks[i], chunk, true);
85 blosc_set_timestamp(&last);
86 if (_nchunks < 0){
87 printf("ERROR: chunk cannot be updated correctly\n");
88 }
89 sframe_update_time += blosc_elapsed_secs(current, last);
90
91 // Frame
92 blosc_set_timestamp(¤t);
93 _nchunks = blosc2_schunk_update_chunk(schunk_cframe, update_chunks[i], chunk, true);
94 blosc_set_timestamp(&last);
95 free(chunk);
96 if (_nchunks <= 0){
97 printf("ERROR: chunk cannot be updated correctly\n");
98 }
99 cframe_update_time += blosc_elapsed_secs(current, last);
100 }
101
102 printf("[Sframe Update] Elapsed time:\t %6.3f s. Total sframe size: %.3" PRId64 " bytes\n",
103 sframe_update_time, schunk_sframe->cbytes);
104 printf("[Cframe Update] Elapsed time:\t %6.3f s. Total cframe size: %.3" PRId64 " bytes\n",
105 cframe_update_time, schunk_cframe->cbytes);
106
107 /* Free resources */
108 free(update_chunks);
109 free(data);
110 }
111
test_insert(blosc2_schunk * schunk_sframe,blosc2_schunk * schunk_cframe)112 void test_insert(blosc2_schunk* schunk_sframe, blosc2_schunk* schunk_cframe) {
113 blosc_timestamp_t last, current;
114 double cframe_insert_time, sframe_insert_time;
115
116 size_t isize = CHUNKSIZE * sizeof(int32_t);
117 int32_t* data = malloc(isize);
118
119 // Random insert list
120 int32_t* insert_chunks = malloc(sizeof(int32_t) * iterations);
121 srand(time(NULL));
122 for (int i = 0; i < iterations; i++) {
123 insert_chunks[i] = rand() % schunk_sframe->nchunks;
124 }
125
126 printf("*******************************************************\n");
127 printf("****************** Inserting %d chunks *****************\n", iterations);
128 printf("*******************************************************\n");
129
130 // Update the sframe chunks
131 sframe_insert_time = 0.0;
132 cframe_insert_time = 0.0;
133 int32_t datasize = sizeof(int32_t) * CHUNKSIZE;
134 int32_t chunksize = sizeof(int32_t) * CHUNKSIZE + BLOSC_MAX_OVERHEAD;
135 uint8_t* chunk;
136 int csize;
137 int _nchunks;
138 for (int i = 0; i < iterations; i++) {
139 // Generate data
140 for (int j = 0; j < CHUNKSIZE; j++) {
141 data[j] = j + i * CHUNKSIZE;
142 }
143 chunk = malloc(chunksize);
144 csize = blosc2_compress_ctx(schunk_sframe->cctx, data, datasize, chunk, chunksize);
145 if (csize < 0) {
146 printf("ERROR: chunk cannot be compressed\n");
147 }
148 // Sframe
149 blosc_set_timestamp(¤t);
150 _nchunks = blosc2_schunk_insert_chunk(schunk_sframe, insert_chunks[i], chunk, true);
151 blosc_set_timestamp(&last);
152 if (_nchunks < 0){
153 printf("ERROR: chunk cannot be updated correctly\n");
154 }
155 sframe_insert_time += blosc_elapsed_secs(current, last);
156
157 // Frame
158 blosc_set_timestamp(¤t);
159 _nchunks = blosc2_schunk_update_chunk(schunk_cframe, insert_chunks[i], chunk, true);
160 blosc_set_timestamp(&last);
161 free(chunk);
162 if (_nchunks <= 0){
163 printf("ERROR: chunk cannot be updated correctly\n");
164 }
165 cframe_insert_time += blosc_elapsed_secs(current, last);
166 }
167
168 printf("[Sframe Insert] Elapsed time:\t %6.3f s. Total sframe size: %.3" PRId64 " bytes \n",
169 sframe_insert_time, schunk_sframe->cbytes);
170 printf("[Cframe Insert] Elapsed time:\t %6.3f s. Total cframe size: %.3" PRId64 " bytes \n",
171 cframe_insert_time, schunk_cframe->cbytes);
172
173
174 /* Free resources */
175 free(insert_chunks);
176 free(data);
177 }
178
test_reorder(blosc2_schunk * schunk_sframe,blosc2_schunk * schunk_cframe)179 void test_reorder(blosc2_schunk* schunk_sframe, blosc2_schunk* schunk_cframe) {
180 blosc_timestamp_t last, current;
181 double cframe_reorder_time, sframe_reorder_time;
182
183 // Reorder list
184 int *offsets_order = malloc(sizeof(int) * schunk_sframe->nchunks);
185 for (int i = 0; i < schunk_sframe->nchunks; ++i) {
186 offsets_order[i] = (i + 3) % schunk_sframe->nchunks;
187 }
188
189 printf("*******************************************************\n");
190 printf("****************** Reordering chunks ******************\n");
191 printf("*******************************************************\n");
192
193 // Reorder sframe
194 blosc_set_timestamp(¤t);
195 int err = blosc2_schunk_reorder_offsets(schunk_sframe, offsets_order);
196 blosc_set_timestamp(&last);
197 if (err < 0) {
198 printf("ERROR: cannot reorder chunks\n");
199 }
200 sframe_reorder_time = blosc_elapsed_secs(current, last);
201
202 // Reorder frame
203 blosc_set_timestamp(¤t);
204 err = blosc2_schunk_reorder_offsets(schunk_cframe, offsets_order);
205 blosc_set_timestamp(&last);
206 if (err < 0) {
207 printf("ERROR: cannot reorder chunks\n");
208 }
209 cframe_reorder_time = blosc_elapsed_secs(current, last);
210
211 printf("[Sframe Update] Elapsed time:\t %f s. Total sframe size: %.3" PRId64 " bytes \n",
212 sframe_reorder_time, schunk_sframe->cbytes);
213 printf("[Cframe Update] Elapsed time:\t %f s. Total cframe size: %.3" PRId64 " bytes \n",
214 cframe_reorder_time, schunk_cframe->cbytes);
215
216 /* Free resources */
217 free(offsets_order);
218 }
219
test_create_sframe_frame(char * operation)220 void test_create_sframe_frame(char* operation) {
221 blosc_timestamp_t last, current;
222 double cframe_append_time, sframe_append_time, cframe_decompress_time, sframe_decompress_time;
223
224 int64_t nbytes, cbytes;
225 size_t isize = CHUNKSIZE * sizeof(int32_t);
226 int dsize;
227 float totalsize = (float)(isize * nchunks);
228 int32_t* data = malloc(isize);
229 int32_t* data_dest = malloc(isize);
230
231 blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
232 blosc2_dparams dparams = BLOSC2_DPARAMS_DEFAULTS;
233
234 blosc2_schunk* schunk_sframe;
235 blosc2_schunk* schunk_cframe;
236
237 /* Initialize the Blosc compressor */
238 blosc_init();
239 printf("*******************************************************\n");
240 printf("***** Creating the frame and sframe with %d chunks ****\n", nchunks);
241 printf("*******************************************************\n");
242 /* Create a frame container */
243 cparams.typesize = sizeof(int32_t);
244
245 cparams.nthreads = 2;
246 dparams.nthreads = 2;
247
248 blosc2_storage storage = {.contiguous=false, .urlpath="dir.b2frame", .cparams=&cparams, .dparams=&dparams};
249 blosc2_remove_urlpath(storage.urlpath);
250 schunk_sframe = blosc2_schunk_new(&storage);
251
252 blosc2_storage storage2 = {.contiguous=true, .urlpath="test_cframe.b2frame", .cparams=&cparams, .dparams=&dparams};
253 blosc2_remove_urlpath(storage2.urlpath);
254 schunk_cframe = blosc2_schunk_new(&storage2);
255
256 printf("Test comparation frame vs sframe with %d chunks.\n", nchunks);
257
258 // Feed it with data
259 sframe_append_time=0.0;
260 cframe_append_time=0.0;
261 blosc_set_timestamp(¤t);
262 for (int nchunk = 0; nchunk < nchunks; nchunk++) {
263 for (int i = 0; i < CHUNKSIZE; i++) {
264 data[i] = i + nchunk * CHUNKSIZE;
265 }
266 blosc_set_timestamp(¤t);
267 blosc2_schunk_append_buffer(schunk_sframe, data, isize);
268 blosc_set_timestamp(&last);
269 sframe_append_time += blosc_elapsed_secs(current, last);
270
271 blosc_set_timestamp(¤t);
272 blosc2_schunk_append_buffer(schunk_cframe, data, isize);
273 blosc_set_timestamp(&last);
274 cframe_append_time += blosc_elapsed_secs(current, last);
275 }
276 printf("[Sframe Compr] Elapsed time:\t %6.3f s. Processed data: %.3f GB (%.3f GB/s)\n",
277 sframe_append_time, totalsize / GB, totalsize / (GB * sframe_append_time));
278 printf("[Cframe Compr] Elapsed time:\t %6.3f s. Processed data: %.3f GB (%.3f GB/s)\n",
279 cframe_append_time, totalsize / GB, totalsize / (GB * cframe_append_time));
280
281 /* Gather some info */
282 nbytes = schunk_sframe->nbytes;
283 cbytes = schunk_sframe->cbytes;
284 printf("Compression super-chunk-sframe: %ld -> %ld (%.1fx)\n",
285 (long)nbytes, (long)cbytes, (1. * nbytes) / cbytes);
286 nbytes = schunk_cframe->nbytes;
287 cbytes = schunk_cframe->cbytes;
288 printf("Compression super-chunk-cframe: %ld -> %ld (%.1fx)\n",
289 (long)nbytes, (long)cbytes, (1. * nbytes) / cbytes);
290
291 // Decompress the data
292 sframe_decompress_time = 0;
293 cframe_decompress_time = 0;
294 for (int nchunk = 0; nchunk < nchunks; nchunk++) {
295 // Sframe
296 blosc_set_timestamp(¤t);
297 dsize = blosc2_schunk_decompress_chunk(schunk_sframe, nchunk, (void *) data_dest, isize);
298 blosc_set_timestamp(&last);
299 if (dsize < 0) {
300 printf("Decompression error sframe. Error code: %d\n", dsize);
301 }
302 assert (dsize == (int)isize);
303 sframe_decompress_time += blosc_elapsed_secs(current, last);
304 // Frame
305 blosc_set_timestamp(¤t);
306 dsize = blosc2_schunk_decompress_chunk(schunk_cframe, nchunk, (void *) data_dest, isize);
307 blosc_set_timestamp(&last);
308 if (dsize < 0) {
309 printf("Decompression error cframe. Error code: %d\n", dsize);
310 }
311 assert (dsize == (int)isize);
312 cframe_decompress_time += blosc_elapsed_secs(current, last);
313 }
314
315 printf("[Sframe Decompr] Elapsed time:\t %6.3f s. Processed data: %.3f GB (%.3f GB/s)\n",
316 sframe_decompress_time, totalsize / GB, totalsize / (GB * sframe_decompress_time));
317 printf("[Cframe Decompr] Elapsed time:\t %6.3f s. Processed data: %.3f GB (%.3f GB/s)\n",
318 cframe_decompress_time, totalsize / GB, totalsize / (GB * cframe_decompress_time));
319
320 printf("Decompression successful!\n");
321
322 printf("Successful roundtrip!\n");
323
324 /* Free resources */
325 free(data_dest);
326 free(data);
327
328 if (operation != NULL) {
329 if (strcmp(operation, "insert") == 0) {
330 test_insert(schunk_sframe, schunk_cframe);
331 }
332 else if (strcmp(operation, "update") == 0) {
333 test_update(schunk_sframe, schunk_cframe);
334 }
335 else if (strcmp(operation, "reorder") == 0) {
336 test_reorder(schunk_sframe, schunk_cframe);
337 }
338 }
339
340
341 blosc2_remove_urlpath(schunk_sframe->storage->urlpath);
342 blosc2_remove_urlpath(schunk_cframe->storage->urlpath);
343 blosc2_schunk_free(schunk_sframe);
344 blosc2_schunk_free(schunk_cframe);
345 /* Destroy the Blosc environment */
346 blosc_destroy();
347
348 }
349
main(int argc,char * argv[])350 int main(int argc, char* argv[]) {
351 char* operation;
352
353 if (argc >= 5) {
354 printf("Usage: ./sframe_bench [nchunks] [insert | update | reorder] [num operations]\n");
355 exit(1);
356 }
357 else if (argc >= 2) {
358 nchunks = (int)strtol(argv[1], NULL, 10);
359 }
360 if (argc >= 3) {
361 operation = argv[2];
362 }
363 if (argc == 4) {
364 iterations = (int)strtol(argv[3], NULL, 10);
365 }
366
367 test_create_sframe_frame(operation);
368
369 return 0;
370 }
371