File: performance.cpp

package info (click to toggle)
charls 2.4.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 17,636 kB
  • sloc: cpp: 13,392; ansic: 986; makefile: 22
file content (162 lines) | stat: -rw-r--r-- 5,867 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright (c) Team CharLS.
// SPDX-License-Identifier: BSD-3-Clause

#include "performance.h"

#include "portable_anymap_file.h"
#include "util.h"

#include <chrono>
#include <iostream>
#include <ratio>
#include <tuple>
#include <vector>

using charls::frame_info;
using charls::jpegls_decoder;
using charls::jpegls_encoder;
using charls::jpegls_error;
using std::cout;
using std::istream;
using std::milli;
using std::vector;
using std::chrono::duration;
using std::chrono::steady_clock;

namespace {

void test_performance(const int loop_count)
{
    // RGBA image (This is a common PNG sample)
    test_file("test/alphatest.raw", 0, {380, 287}, 8, 4, false, loop_count);

    // 16 bit mono
    test_file("test/MR2_UNC", 1728, {1024, 1024}, 16, 1, true, loop_count);

    // 8 bit mono
    test_file("test/0015.raw", 0, {1024, 1024}, 8, 1, false, loop_count);

    // 8 bit color
    test_file("test/desktop.ppm", 40, {1280, 1024}, 8, 3, false, loop_count);
}

} // namespace


void performance_tests(const int loop_count)
{
#ifdef _DEBUG
    cout << "NOTE: running performance test in debug mode, performance may be slow!\n";
#endif
    cout << "Test Perf (with loop count " << loop_count << ")\n";
    test_performance(loop_count);
}

void test_large_image_performance_rgb8(const int loop_count)
{
    // Note: the test images are very large and not included in the repository.
    //       The images can be downloaded from: http://imagecompression.info/test_images/

#ifdef _DEBUG
    cout << "NOTE: running performance test in debug mode, performance may be slow!\n";
#endif
    cout << "Test Large Images Performance\n";

    try
    {
        test_portable_anymap_file("test/rgb8bit/artificial.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/big_building.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/big_tree.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/bridge.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/cathedral.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/deer.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/fireworks.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/flower_foveon.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/hdr.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/leaves_iso_200.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/leaves_iso_1600.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/nightshot_iso_100.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/nightshot_iso_1600.ppm", loop_count);
        test_portable_anymap_file("test/rgb8bit/spider_web.ppm", loop_count);
    }
    catch (const istream::failure& error)
    {
        cout << "Test failed " << error.what() << "\n";
    }
}

void decode_performance_tests(const int loop_count)
{
    cout << "Test decode performance with loop count " << loop_count << "\n";

    try
    {
        // This test expect the file decodetest.jls to exist.
        // It can be any valid JPEG-LS file.
        // Changing the content of this file allows different performance measurements.
        const vector<uint8_t> encoded_source{read_file("decodetest.jls")};

        // Pre-allocate the destination outside the measurement loop.
        // std::vector initializes its elements and this step needs to be excluded from the measurement.
        vector<uint8_t> destination(jpegls_decoder{encoded_source, true}.destination_size());

        const auto start{steady_clock::now()};
        for (int i{}; i != loop_count; ++i)
        {
            const jpegls_decoder decoder{encoded_source, true};

            decoder.decode(destination);
        }

        const auto end{steady_clock::now()};
        const auto diff{end - start};
        cout << "Total decoding time is: " << duration<double, milli>(diff).count() << " ms\n";
        cout << "Decoding time per image: " << duration<double, milli>(diff).count() / loop_count << " ms\n";
    }
    catch (const jpegls_error& e)
    {
        cout << "Decode failure: " << e.what() << "\n";
    }
    catch (const std::ios_base::failure& e)
    {
        cout << "IO failure (missing decodetest.jls?): " << e.what() << "\n";
    }
}

void encode_performance_tests(const int loop_count)
{
    cout << "Test encode performance with loop count " << loop_count << "\n";

    const charls_test::portable_anymap_file anymap_file("encode-test.pnm");

    try
    {
        const frame_info info{static_cast<uint32_t>(anymap_file.width()), static_cast<uint32_t>(anymap_file.height()),
                              anymap_file.bits_per_sample(), anymap_file.component_count()};
        const auto interleave_mode{anymap_file.component_count() > 1 ? charls::interleave_mode::sample
                                                                     : charls::interleave_mode::none};

        jpegls_encoder encoder1;
        encoder1.frame_info(info).interleave_mode(interleave_mode);
        vector<uint8_t> destination(encoder1.estimated_destination_size());

        const auto start{steady_clock::now()};
        for (int i{}; i != loop_count; ++i)
        {
            jpegls_encoder encoder2;
            encoder2.frame_info(info).interleave_mode(interleave_mode);
            encoder2.destination(destination);

            std::ignore = encoder2.encode(anymap_file.image_data());
        }

        const auto end{steady_clock::now()};
        const auto diff{end - start};
        cout << "Total encoding time is: " << duration<double, milli>(diff).count() << " ms\n";
        cout << "Encoding time per image: " << duration<double, milli>(diff).count() / loop_count << " ms\n";
    }
    catch (const jpegls_error& e)
    {
        cout << "Encoding failure: " << e.what() << "\n";
    }
}