Gamp v0.0.7-67-g7798ac4
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
test_stringfmt_perf_impl.cpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2024 Gothel Software e.K.
4 *
5 * ***
6 *
7 * SPDX-License-Identifier: MIT
8 *
9 * This Source Code Form is subject to the terms of the MIT License
10 * If a copy of the MIT was not distributed with this
11 * file, You can obtain one at https://opensource.org/license/mit/.
12 *
13 */
14#include <sys/types.h>
15#include <cassert>
16#include <cstdint>
17#include <cstdio>
18#include <cstring>
19#include <iostream>
20#include <limits>
21
22#include <jau/basic_types.hpp>
23#include <jau/cpp_lang_util.hpp>
24#include <jau/cpp_pragma.hpp>
25#include <jau/float_types.hpp>
26#include <jau/int_types.hpp>
27#include <jau/string_cfmt.hpp>
29#include <jau/string_util.hpp>
30#include <jau/test/catch2_ext.hpp>
31#include <jau/type_concepts.hpp>
33
34#ifdef HAS_STD_FORMAT
35 #include <format>
36#endif
37
38using namespace std::literals;
39
40using namespace jau::float_literals;
41
42using namespace jau::int_literals;
43
44/// Execute with `test_stringfmt_perf_impl --perf-analysis`
45
46static uint32_t digits10_loop0(uint64_t v) noexcept {
47 static constexpr const size_t char32buf_maxlen = 32;
48 char buf_[char32buf_maxlen];
49 char * d = buf_;
50 const char * const d_end_num = d + char32buf_maxlen;
51 uint32_t l = 0;
52 do {
53 ++l;
54 v /= 10;
55 } while( v && d < d_end_num);
56 return l;
57}
58static uint32_t digits10_loop1(uint64_t v) noexcept {
59 static constexpr const size_t char32buf_maxlen = 32;
60 char buf_[char32buf_maxlen];
61 char * d = buf_;
62 const char * const d_end_num = d + char32buf_maxlen;
63 do {
64 *(d++) = char('0' + (v % 10_u64));
65 v /= 10;
66 } while( v && d < d_end_num);
67 return uint32_t(d - buf_);
68}
69
70TEST_CASE("fast_log_benchmark_digits10", "[benchmark][jau][math][log]") {
71 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
72 WARN("Benchmark with " + std::to_string(loops) + " loops");
73 CHECK(true);
74
75 const double log2_10 = std::log2<uint64_t>(10);
76 const uint64_t i1 = std::numeric_limits<uint64_t>::max(); // Value = 18446744073709551615 (0xffffffffffffffff)
77 const uint32_t i1_d10 = 20;
78
79 BENCHMARK("O(n) loop0 bench") {
80 volatile size_t res = 0;
81 for( size_t i = 0; i < loops; ++i ) {
82 uint32_t l = digits10_loop0(i1);
83 REQUIRE(i1_d10 == l);
84 res = res + l;
85 }
86 return res;
87 };
88 BENCHMARK("O(n) loop1 bench") {
89 volatile size_t res = 0;
90 for( size_t i = 0; i < loops; ++i ) {
91 uint32_t l = digits10_loop1(i1);
92 REQUIRE(i1_d10 == l);
93 res = res + l;
94 }
95 return res;
96 };
97 BENCHMARK("log10(x) bench") {
98 volatile size_t res = 0;
99 for( size_t i = 0; i < loops; ++i ) {
100 uint32_t l = 1 + static_cast<uint32_t>(std::log10<uint64_t>(i1));
101 REQUIRE(i1_d10 == l);
102 res = res + l;
103 }
104 return res;
105 };
106 BENCHMARK("log2(x)/log2(10) bench") {
107 volatile size_t res = 0;
108 for( size_t i = 0; i < loops; ++i ) {
109 uint32_t l = 1 + static_cast<uint32_t>(std::log2<uint64_t>(i1) / log2_10);
110 REQUIRE(i1_d10 == l);
111 res = res + l;
112 }
113 return res;
114 };
115}
116
117TEST_CASE("jau_cfmt_benchmark_append_integral00", "[benchmark][jau][std::string][format_string]") {
118 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
119 WARN("Benchmark with " + std::to_string(loops) + " loops");
120 CHECK(true);
121
122 const uint64_t i1 = std::numeric_limits<uint64_t>::max(); // Value = 18446744073709551615 (0xffffffffffffffff)
123 static constexpr const char *format_check_exp = "18446744073709551615";
126 // opts.addFlag('0');
127 o1.setConversion('u');
128 std::cout << "flags: " << o1 << "\n";
129
130 {
131 std::string s;
133
134 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
135 REQUIRE(format_check_exp == s);
136
137 s.clear();
138 jau::cfmt::impl::append_integral_simple(s, s.max_size(), i1, false, o1);
139 REQUIRE(format_check_exp == s);
140 }
141
142 BENCHMARK("append_integral rsrved bench") {
143 volatile size_t res = 0;
144 for( size_t i = 0; i < loops; ++i ) {
145 std::string s;
147
148 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
149 REQUIRE(format_check_exp == s);
150 res = res + s.size();
151 }
152 return res;
153 };
154 BENCHMARK("append_integral_simple rsrved bench") {
155 volatile size_t res = 0;
156 for( size_t i = 0; i < loops; ++i ) {
157 std::string s;
159
160 jau::cfmt::impl::append_integral_simple(s, s.max_size(), i1, false, o1);
161 REQUIRE(format_check_exp == s);
162 res = res + s.size();
163 }
164 return res;
165 };
166
167 BENCHMARK("snprintf rsrved bench") {
168 volatile size_t res = 0;
169 for( size_t i = 0; i < loops; ++i ) {
170 std::string s;
171 const size_t bsz = jau::cfmt::default_string_capacity + 1; // including EOS
172 s.reserve(bsz); // incl. EOS
173 s.resize(bsz - 1); // excl. EOS
174 size_t nchars = std::snprintf(&s[0], bsz, "%zu", i1);
175 if( nchars < bsz ) {
176 s.resize(nchars);
177 }
178 REQUIRE(format_check_exp == s);
179 res = res + nchars;
180 }
181 return res;
182 };
183}
184
185TEST_CASE("jau_cfmt_benchmark_append_integral01", "[benchmark][jau][std::string][format_string]") {
186 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
187 WARN("Benchmark with " + std::to_string(loops) + " loops");
188 CHECK(true);
189
190 const uint64_t i1 = std::numeric_limits<uint64_t>::max(); // Value = 18446744073709551615 (0xffffffffffffffff)
191 static constexpr const char *format_check_exp1 = " 018446744073709551615";
192 static constexpr const char *format_check_exp0 = " 018446744073709551615";
195 o1.setWidth(25);
196 o1.setPrecision(21);
197 o1.setConversion('u');
198 std::cout << "flags: " << o1 << "\n";
199
200 {
201 std::string s;
203
204 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
205 REQUIRE(format_check_exp1 == s);
206 }
207
208 BENCHMARK("append_integral rsrved bench") {
209 volatile size_t res = 0;
210 for( size_t i = 0; i < loops; ++i ) {
211 std::string s;
213
214 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
215 REQUIRE(format_check_exp1 == s);
216 res = res + s.size();
217 }
218 return res;
219 };
220
221 BENCHMARK("snprintf rsrved bench") {
222 volatile size_t res = 0;
223 for( size_t i = 0; i < loops; ++i ) {
224 std::string s;
225 const size_t bsz = jau::cfmt::default_string_capacity + 1; // including EOS
226 s.reserve(bsz); // incl. EOS
227 s.resize(bsz - 1); // excl. EOS
228 size_t nchars = std::snprintf(&s[0], bsz, "%25.21zu", i1);
229 if( nchars < bsz ) {
230 s.resize(nchars);
231 }
232 REQUIRE(format_check_exp0 == s);
233 res = res + nchars;
234 }
235 return res;
236 };
237}
238
239TEST_CASE("jau_cfmt_benchmark_append_integral02", "[benchmark][jau][std::string][format_string]") {
240 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
241 WARN("Benchmark with " + std::to_string(loops) + " loops");
242 CHECK(true);
243
244 const uint64_t i1 = std::numeric_limits<uint64_t>::max(); // Value = 18446744073709551615 (0xffffffffffffffff)
245 static constexpr const char *format_check_exp1 = " 018'446'744'073'709'551'615";
246 static constexpr const char *format_check_exp0 = " 018446744073709551615";
249 o1.addFlag('\'');
250 o1.setWidth(31);
251 o1.setPrecision(27);
252 o1.setConversion('u');
253 std::cout << "flags: " << o1 << "\n";
254
255 {
256 std::string s;
258
259 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
260 REQUIRE(format_check_exp1 == s);
261 }
262
263 BENCHMARK("append_integral rsrved bench") {
264 volatile size_t res = 0;
265 for( size_t i = 0; i < loops; ++i ) {
266 std::string s;
268
269 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
270 REQUIRE(format_check_exp1 == s);
271 res = res + s.size();
272 }
273 return res;
274 };
275
276 BENCHMARK("snprintf rsrved bench") {
277 volatile size_t res = 0;
278 for( size_t i = 0; i < loops; ++i ) {
279 std::string s;
280 const size_t bsz = jau::cfmt::default_string_capacity + 1; // including EOS
281 s.reserve(bsz); // incl. EOS
282 s.resize(bsz - 1); // excl. EOS
283 size_t nchars = std::snprintf(&s[0], bsz, "%25.21zu", i1);
284 if( nchars < bsz ) {
285 s.resize(nchars);
286 }
287 REQUIRE(format_check_exp0 == s);
288 res = res + nchars;
289 }
290 return res;
291 };
292}
constexpr const size_t default_string_capacity
Default string reserved capacity w/o EOS (511)
@ z
size_t or ssize_t integer
constexpr bool setConversion(char fmt_literal) noexcept
constexpr bool addFlag(char c) noexcept
constexpr void setWidth(uint32_t v)
constexpr void setPrecision(uint32_t v)
static int loops
static uint32_t digits10_loop0(uint64_t v) noexcept
Execute with test_stringfmt_perf_impl --perf-analysis
static uint32_t digits10_loop1(uint64_t v) noexcept
TEST_CASE("fast_log_benchmark_digits10", "[benchmark][jau][math][log]")