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 Example program demonstrating use of the Blosc filter from C code.
7
8 To compile this program:
9
10 $ gcc frame_simple.c -o frame_simple -lblosc2
11
12 To run:
13
14 $ ./frame_simple
15 Blosc version info: 2.0.0a6.dev ($Date:: 2018-05-18 #$)
16 Compression ratio: 381.5 MB -> 9.5 MB (40.2x)
17 Compression time: 0.705 s, 541.0 MB/s
18 Time for schunk -> frame: 0.00796 s, 47905.3 MB/s
19 Frame length in memory: 9940344 bytes
20 Frame length on disk: 9940344 bytes
21 Time for frame -> fileframe (frame_simple.b2frame): 0.0108 s, 35159.6 MB/s
22 Time for fileframe (frame_simple.b2frame) -> frame : 0.000254 s, 1.5e+06 MB/s
23 Time for frame -> schunk: 1.1e-05 s, 3.48e+07 MB/s
24 Time for fileframe -> schunk: 1.25e-05 s, 3.05e+07 MB/s
25 Successful roundtrip schunk <-> frame <-> fileframe !
26
27 */
28
29 #include <stdio.h>
30 #include <assert.h>
31 #include <blosc2.h>
32
33 #define KB 1024.
34 #define MB (1024*KB)
35 #define GB (1024*MB)
36
37 #define CHUNKSIZE (200 * 1000)
38 #define NCHUNKS 100
39 #define NTHREADS 4
40
41
main(void)42 int main(void) {
43
44 blosc_init();
45
46 static int32_t data[CHUNKSIZE];
47 static int32_t data_dest[CHUNKSIZE];
48 static int32_t data_dest2[CHUNKSIZE];
49 size_t isize = CHUNKSIZE * sizeof(int32_t);
50 int64_t nbytes, cbytes;
51 int i, nchunk;
52 int nchunks;
53 blosc_timestamp_t last, current;
54 double ttotal;
55
56 printf("Blosc version info: %s (%s)\n",
57 BLOSC_VERSION_STRING, BLOSC_VERSION_DATE);
58
59 /* Create a super-chunk container */
60 blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
61 cparams.typesize = sizeof(int32_t);
62 cparams.compcode = BLOSC_LZ4;
63 cparams.clevel = 9;
64 cparams.nthreads = NTHREADS;
65 blosc2_dparams dparams = BLOSC2_DPARAMS_DEFAULTS;
66 dparams.nthreads = NTHREADS;
67 blosc2_storage storage = {.cparams=&cparams, .dparams=&dparams};
68 blosc2_schunk* schunk = blosc2_schunk_new(&storage);
69
70 // Add some data
71 blosc_set_timestamp(&last);
72 for (nchunk = 0; nchunk < NCHUNKS; nchunk++) {
73 for (i = 0; i < CHUNKSIZE; i++) {
74 data[i] = i * nchunk;
75 }
76 nchunks = blosc2_schunk_append_buffer(schunk, data, isize);
77 assert(nchunks == nchunk + 1);
78 }
79
80 // Add some vlmetalayers data
81 uint32_t content_len = 10;
82 uint8_t *content = malloc(content_len);
83 for (uint32_t j = 0; j < content_len; ++j) {
84 content[j] = (uint8_t) j;
85 }
86 int umlen = blosc2_vlmeta_add(schunk, "vlmetalayer", content, content_len, NULL);
87 free(content);
88 if (umlen < 0) {
89 printf("Cannot write vlmetalayers chunk");
90 return umlen;
91 }
92
93 /* Gather some info */
94 nbytes = schunk->nbytes;
95 cbytes = schunk->cbytes;
96 blosc_set_timestamp(¤t);
97 ttotal = blosc_elapsed_secs(last, current);
98 printf("Compression ratio: %.1f MB -> %.1f MB (%.1fx)\n",
99 nbytes / MB, cbytes / MB, (1. * nbytes) / cbytes);
100 printf("Compression time: %.3g s, %.1f MB/s\n",
101 ttotal, nbytes / (ttotal * MB));
102 uint8_t* vlmetalayer;
103
104 blosc2_vlmeta_get(schunk, "vlmetalayer", &vlmetalayer, &content_len);
105 printf("Variable-length metalayer length: %d\n", content_len);
106 for (int j = 0; j < content_len; ++j) {
107 printf("%3d", vlmetalayer[j]);
108 }
109 printf("\n");
110 free(vlmetalayer);
111
112 // Start different conversions between schunks, frames and fileframes
113
114 // super-chunk -> cframe (contiguous frame, or buffer)
115 blosc_set_timestamp(&last);
116 uint8_t* cframe;
117 bool cframe_needs_free;
118 int64_t frame_len = blosc2_schunk_to_buffer(schunk, &cframe, &cframe_needs_free);
119 if (frame_len < 0) {
120 return frame_len;
121 }
122 blosc_set_timestamp(¤t);
123 ttotal = blosc_elapsed_secs(last, current);
124 printf("Time for schunk -> frame: %.3g s, %.1f MB/s\n",
125 ttotal, nbytes / (ttotal * MB));
126 printf("Frame length in memory: %ld bytes\n", (long)frame_len);
127
128 // super-chunk -> fileframe (contiguous frame, on-disk)
129 remove("frame_simple.b2frame");
130 blosc_set_timestamp(&last);
131 frame_len = blosc2_schunk_to_file(schunk, "frame_simple.b2frame");
132 if (frame_len < 0) {
133 return frame_len;
134 }
135 printf("Frame length on disk: %ld bytes\n", (long)frame_len);
136 blosc_set_timestamp(¤t);
137 ttotal = blosc_elapsed_secs(last, current);
138 printf("Time for frame -> fileframe (frame_simple.b2frame): %.3g s, %.1f GB/s\n",
139 ttotal, nbytes / (ttotal * GB));
140
141 // fileframe (file) -> schunk2 (on-disk contiguous, super-chunk)
142 blosc_set_timestamp(&last);
143 blosc2_schunk* schunk2 = blosc2_schunk_open("file:///frame_simple.b2frame");
144 blosc_set_timestamp(¤t);
145 ttotal = blosc_elapsed_secs(last, current);
146 printf("Time for fileframe (%s) -> frame : %.3g s, %.1f GB/s\n",
147 schunk2->storage->urlpath, ttotal, nbytes / (ttotal * GB));
148
149 // frame1 (in-memory) -> schunk
150 blosc_set_timestamp(&last);
151 // The next creates a schunk from the in-memory frame
152 blosc2_schunk* schunk1 = blosc2_schunk_from_buffer(cframe, frame_len, false);
153 if (schunk1 == NULL) {
154 printf("Bad conversion frame1 -> schunk1!\n");
155 return -1;
156 }
157 blosc_set_timestamp(¤t);
158 ttotal = blosc_elapsed_secs(last, current);
159 printf("Time for frame -> schunk: %.3g s, %.1f GB/s\n",
160 ttotal, nbytes / (ttotal * GB));
161
162
163 /* Retrieve and decompress the chunks from the super-chunks and compare values */
164 for (nchunk = 0; nchunk < NCHUNKS; nchunk++) {
165 int32_t dsize = blosc2_schunk_decompress_chunk(schunk1, nchunk, data_dest, isize);
166 if (dsize < 0) {
167 printf("Decompression error in schunk1. Error code: %d\n", dsize);
168 return dsize;
169 }
170 dsize = blosc2_schunk_decompress_chunk(schunk2, nchunk, data_dest2, isize);
171 if (dsize < 0) {
172 printf("Decompression error in schunk2. Error code: %d\n", dsize);
173 return dsize;
174 }
175 /* Check integrity of this chunk */
176 for (i = 0; i < CHUNKSIZE; i++) {
177 assert (data_dest[i] == i * nchunk);
178 assert (data_dest2[i] == i * nchunk);
179 }
180 }
181 printf("Successful roundtrip schunk <-> frame <-> fileframe !\n");
182
183 blosc2_vlmeta_get(schunk1, "vlmetalayer", &vlmetalayer, &content_len);
184 for (int j = 0; j < content_len; ++j) {
185 printf("%3d", vlmetalayer[j]);
186 }
187 printf("\n");
188 free(vlmetalayer);
189 blosc2_vlmeta_get(schunk2, "vlmetalayer", &vlmetalayer, &content_len);
190 for (int j = 0; j < content_len; ++j) {
191 printf("%3d", vlmetalayer[j]);
192 }
193 printf("\n");
194 free(vlmetalayer);
195
196 /* Free resources */
197 blosc2_schunk_free(schunk);
198 blosc2_schunk_free(schunk1);
199 blosc2_schunk_free(schunk2);
200 if (cframe_needs_free) {
201 free(cframe);
202 }
203 blosc_destroy();
204
205 return 0;
206 }
207