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 Simple benchmark for frame creation.
7
8 To run:
9
10 $ ./create_frame
11
12 *** Creating unitialized ***
13 *** Using fill method! ***
14
15 *** Creating *contiguous* super-chunk for *blosclz*
16 Compression ratio: 186.26 GB -> 0.17 KB (1162790697.7x)
17 Compression time: 8.5e-06 s, 21399.9 TB/s
18 Decompression time: 0.0628 s, 2965.1 GB/s
19
20 *** Creating *sparse* super-chunk for *blosclz*
21 Compression ratio: 186.26 GB -> 3906.29 KB (49999.5x)
22 Compression time: 0.00294 s, 61.8 TB/s
23 Decompression time: 0.00424 s, 43959.2 GB/s
24
25 *** Creating *contiguous* super-chunk for *lz4*
26 Compression ratio: 186.26 GB -> 0.17 KB (1162790697.7x)
27 Compression time: 4.71e-06 s, 38636.1 TB/s
28 Decompression time: 0.0701 s, 2656.7 GB/s
29
30 *** Creating *sparse* super-chunk for *lz4*
31 Compression ratio: 186.26 GB -> 3906.29 KB (49999.5x)
32 Compression time: 0.00311 s, 58.5 TB/s
33 Decompression time: 0.0101 s, 18516.4 GB/s
34
35 Process finished with exit code 0
36
37 */
38
39 #include <stdio.h>
40 #include <blosc2.h>
41
42 #define KB (1024.)
43 #define MB (1024 * KB)
44 #define GB (1024 * MB)
45 #define TB (1024 * GB)
46
47 #define CHUNKSHAPE (500 * 1000)
48 #define NCHUNKS 100000
49 #define NTHREADS 1 // curiously, using 1 single thread is better for the uninitialized values
50
51 // For exercising the optimized chunk creators (un)comment the lines below as you please
52 //#define CREATE_ZEROS
53 #define CREATE_FILL
54 //#define CREATE_LOOP
55
create_cframe(const char * compname,bool contiguous)56 int create_cframe(const char* compname, bool contiguous) {
57 int32_t isize = CHUNKSHAPE * sizeof(int32_t);
58 int32_t* data = malloc(isize);
59 int32_t* data_dest = malloc(isize);
60 int32_t* data_dest2 = malloc(isize);
61 int64_t nbytes, cbytes;
62 int nchunk;
63 blosc_timestamp_t last, current;
64 double ttotal;
65 int compcode = blosc_compname_to_compcode(compname);
66 printf("\n*** Creating *%s* super-chunk for *%s*\n",
67 contiguous ? "contiguous" : "sparse", compname);
68
69 /* Create a super-chunk container */
70 blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
71 cparams.typesize = sizeof(int32_t);
72 cparams.compcode = compcode;
73 cparams.clevel = 9;
74 cparams.nthreads = NTHREADS;
75 //cparams.blocksize = 1024;
76 blosc2_dparams dparams = BLOSC2_DPARAMS_DEFAULTS;
77 dparams.nthreads = NTHREADS;
78 char filename[64];
79 sprintf(filename, "frame_simple-%s.b2frame", compname);
80 blosc2_storage storage = {.cparams=&cparams, .dparams=&dparams,
81 .urlpath=NULL, .contiguous=contiguous};
82 blosc2_schunk* schunk = blosc2_schunk_new(&storage);
83
84 #ifdef CREATE_ZEROS
85 // Precompute chunk of zeros
86 int ret = blosc2_chunk_zeros(cparams, isize, data_dest, isize);
87 #else
88 int ret = blosc2_chunk_uninit(cparams, isize, data_dest, isize);
89 #endif
90 if (ret < 0) {
91 printf("Creation error in special chunk. Error code: %d\n", ret);
92 return ret;
93 }
94
95 // Add some data
96 blosc_set_timestamp(&last);
97
98 int64_t nitems;
99 #ifdef CREATE_FILL
100 // Make nitems a non-divisible number of CHUNKSHAPE
101 nitems = (int64_t)NCHUNKS * CHUNKSHAPE + 1;
102 #ifdef CREATE_ZEROS
103 // Precompute chunk of zeros
104 int special_value = BLOSC2_SPECIAL_ZERO;
105 #else
106 int special_value = BLOSC2_SPECIAL_UNINIT;
107 #endif
108 int rc = blosc2_schunk_fill_special(schunk, nitems, special_value, isize);
109 if (rc < 0) {
110 printf("Error in fill special. Error code: %d\n", rc);
111 return rc;
112 }
113 #else
114 // In these methods, nitems can only be an actual multiple of CHUNKSHAPE
115 nitems = (int64_t)NCHUNKS * CHUNKSHAPE;
116 for (nchunk = 0; nchunk < NCHUNKS; nchunk++) {
117 #ifdef CREATE_LOOP
118 int nchunks = blosc2_schunk_append_chunk(schunk, (uint8_t *) data_dest, true);
119 if (nchunks != nchunk + 1) {
120 printf("Compression error in append chunk. Error code: %d\n", nchunks);
121 return nchunk;
122 }
123 #else
124 for (int i = 0; i < CHUNKSHAPE; i++) {
125 // Different data patterns
126 // data[i] = i * nchunk;
127 // data[i] = nchunk;
128 data[i] = 0;
129 }
130 int nchunks = blosc2_schunk_append_buffer(schunk, data, isize);
131 if (nchunks != nchunk + 1) {
132 printf("Compression error appending in schunk. Error code: %d\n", nchunks);
133 return nchunk;
134 }
135 #endif
136 }
137 #endif
138 blosc_set_timestamp(¤t);
139
140 /* Gather some info */
141 nbytes = schunk->nbytes;
142 cbytes = blosc2_schunk_frame_len(schunk);
143 ttotal = blosc_elapsed_secs(last, current);
144 printf("Compression ratio: %.2f GB -> %.2f KB (%4.1fx)\n",
145 (double)nbytes / GB, (double)cbytes / KB, (double)nbytes / (double)cbytes);
146 printf("Compression time: %.3g s, %.1f TB/s\n",
147 ttotal, (double)nbytes / (ttotal * TB));
148
149 /* Retrieve and decompress the chunks from the super-chunks and compare values */
150 blosc_set_timestamp(&last);
151 int32_t leftover_bytes = (int32_t)((nitems % CHUNKSHAPE) * sizeof(int32_t));
152 int32_t nchunks = leftover_bytes ? NCHUNKS + 1 : NCHUNKS;
153 for (nchunk = 0; nchunk < nchunks; nchunk++) {
154 int32_t dsize = blosc2_schunk_decompress_chunk(schunk, nchunk, data_dest, isize);
155 if (dsize < 0) {
156 printf("Decompression error in schunk. Error code: %d\n", dsize);
157 return dsize;
158 }
159 if ((nchunk == nchunks - 1) && (leftover_bytes > 0)) {
160 if (dsize != leftover_bytes) {
161 printf("Wrong size for last chunk. It is %d and should be: %d\n", dsize, leftover_bytes);
162 return dsize;
163 }
164 }
165 }
166 blosc_set_timestamp(¤t);
167 ttotal = blosc_elapsed_secs(last, current);
168 printf("Decompression time: %.3g s, %.1f GB/s\n",
169 ttotal, (double)nbytes / (ttotal * GB));
170
171 /* Free resources */
172 blosc2_schunk_free(schunk);
173 free(data);
174 free(data_dest);
175 free(data_dest2);
176
177 return 0;
178 }
179
180
main(void)181 int main(void) {
182 #ifdef CREATE_ZEROS
183 printf("\n *** Creating zeros ***\n");
184 #else
185 printf("\n *** Creating unitialized ***\n");
186 #endif
187 #ifdef CREATE_FILL
188 printf(" *** Using fill method! ***\n");
189 #elif defined(CREATE_LOOP)
190 printf(" *** Using loop method! ***\n");
191 #else
192 printf(" *** Using not optimized method! ***\n");
193 #endif
194
195 create_cframe("blosclz", true);
196 create_cframe("blosclz", false);
197 create_cframe("lz4", true);
198 create_cframe("lz4", false);
199 }
200