1 #include <stdio.h>
2 #include <benchmark/benchmark.h>
3 #include "benchmark_png_shared.h"
4 #include <assert.h>
5 
6 class png_decode: public benchmark::Fixture {
7 protected:
8     png_dat inpng[10];
9 
10     /* Backing this on the heap is a more realistic benchmark */
11     uint8_t *output_img_buf = NULL;
12 
13 public:
14     /* Let's make the vanilla version have something extremely compressible */
init_img(png_bytep img_bytes,size_t width,size_t height)15     virtual void init_img(png_bytep img_bytes, size_t width, size_t height) {
16         init_compressible(img_bytes, width*height);
17     }
18 
SetUp(const::benchmark::State & state)19     void SetUp(const ::benchmark::State& state) {
20         output_img_buf = (uint8_t*)malloc(IMWIDTH * IMHEIGHT * 3);
21         assert(output_img_buf != NULL);
22         init_img(output_img_buf, IMWIDTH, IMHEIGHT);
23 
24         /* First we need to author the png bytes to be decoded */
25         for (int i = 0; i < 10; ++i) {
26             inpng[i] = {NULL, 0, 0};
27             encode_png(output_img_buf, &inpng[i], i, IMWIDTH, IMHEIGHT);
28         }
29     }
30 
31     /* State in this circumstance will convey the compression level */
Bench(benchmark::State & state)32     void Bench(benchmark::State &state) {
33         for (auto _ : state) {
34             int compress_lvl = state.range(0);
35             png_parse_dat in = { inpng[compress_lvl].buf };
36             uint32_t width, height;
37             decode_png(&in, (png_bytepp)&output_img_buf, IMWIDTH * IMHEIGHT * 3, width, height);
38         }
39     }
40 
TearDown(const::benchmark::State & state)41     void TearDown(const ::benchmark::State &state) {
42         free(output_img_buf);
43         for (int i = 0; i < 10; ++i) {
44             free(inpng[i].buf);
45         }
46     }
47 };
48 
49 class png_decode_realistic: public png_decode {
50 private:
51     bool test_files_found = false;
52 
53 public:
SetUp(const::benchmark::State & state)54     void SetUp(const ::benchmark::State &state) {
55         output_img_buf = NULL;
56         output_img_buf = (uint8_t*)malloc(IMWIDTH * IMHEIGHT * 3);
57         /* Let's take all the images at different compression levels and jam their bytes into buffers */
58         char test_fname[25];
59         FILE *files[10];
60 
61         /* Set all to NULL */
62         memset(files, 0, sizeof(FILE*));
63 
64         for (size_t i = 0; i < 10; ++i) {
65             sprintf(test_fname, "test_pngs/%1lu.png", i);
66             FILE *in_img = fopen(test_fname, "r");
67             if (in_img == NULL) {
68                 for (size_t j = 0; j < i; ++j) {
69                     if (files[j])
70                         fclose(files[j]);
71                 }
72 
73                 /* For proper cleanup */
74                 for (size_t j = i; j < 10; ++j) {
75                     inpng[i] = { NULL, 0, 0 };
76                 }
77 
78                 return;
79             }
80             files[i] = in_img;
81         }
82 
83         test_files_found = true;
84         /* Now that we've established we have all the png files, let's read all of their bytes into buffers */
85         for (size_t i = 0; i < 10; ++i) {
86             FILE *in_file = files[i];
87             fseek(in_file, 0, SEEK_END);
88             size_t num_bytes = ftell(in_file);
89             rewind(in_file);
90 
91             uint8_t *raw_file = (uint8_t*)malloc(num_bytes);
92             if (raw_file == NULL)
93                 abort();
94 
95             inpng[i].buf = raw_file;
96             inpng[i].len = num_bytes;
97             inpng[i].buf_rem = 0;
98 
99             size_t bytes_read = fread(raw_file, 1, num_bytes, in_file);
100             if (bytes_read != num_bytes) {
101                 fprintf(stderr, "couldn't read all of the bytes for file test_pngs/%lu.png", i);
102                 abort();
103             }
104 
105             fclose(in_file);
106         }
107     }
108 
Bench(benchmark::State & state)109     void Bench(benchmark::State &state) {
110         if (!test_files_found) {
111             state.SkipWithError("Test imagery in test_pngs not found");
112         }
113 
114         png_decode::Bench(state);
115     }
116 };
117 
BENCHMARK_DEFINE_F(png_decode,png_decode)118 BENCHMARK_DEFINE_F(png_decode, png_decode)(benchmark::State &state) {
119     Bench(state);
120 }
121 BENCHMARK_REGISTER_F(png_decode, png_decode)->DenseRange(0, 9, 1)->Unit(benchmark::kMicrosecond);
122 
BENCHMARK_DEFINE_F(png_decode_realistic,png_decode_realistic)123 BENCHMARK_DEFINE_F(png_decode_realistic, png_decode_realistic)(benchmark::State &state) {
124     Bench(state);
125 }
126 BENCHMARK_REGISTER_F(png_decode_realistic, png_decode_realistic)->DenseRange(0, 9, 1)->Unit(benchmark::kMicrosecond);
127