jaulib v1.4.1-17-gd77ace3-dirty
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
test_stringfmt_perf.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 <cinttypes>
17#include <cstdint>
18#include <cstdio>
19#include <cstring>
20#include <iostream>
21#include <limits>
22#include <sstream>
23#include <string_view>
24
25#include <jau/basic_types.hpp>
26#include <jau/cpp_lang_util.hpp>
27#include <jau/cpp_pragma.hpp>
28#include <jau/float_types.hpp>
29#include <jau/int_types.hpp>
30#include <jau/string_cfmt.hpp>
32#include <jau/string_util.hpp>
33#include <jau/test/catch2_ext.hpp>
34#include <jau/type_concepts.hpp>
36
37#ifdef HAS_STD_FORMAT
38 #include <format>
39#endif
40
41using namespace std::literals;
42
43using namespace jau::float_literals;
44
45using namespace jau::int_literals;
46
47/// Execute with `test_stringfmt_perf --perf-analysis`
48TEST_CASE("jau_cfmt_benchmark_str1", "[benchmark][jau][std::string][format_string]") {
49 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
50 WARN("Benchmark with " + std::to_string(loops) + " loops");
51 CHECK(true);
52
53 static constexpr const char *format_check_exp = "format_check: ' Hi World'";
54 BENCHMARK("fmt1.32 format rsrved bench") {
55 std::string str1 = "Hi World";
56
57 volatile size_t res = 0;
58 for( size_t i = 0; i < loops; ++i ) {
59 std::string s = jau::format_string("format_check: '%10s'", str1);
60 REQUIRE(format_check_exp == s);
61 res = res + s.size();
62 }
63 return res;
64 };
65 BENCHMARK("fmtX.32 snprintf rsrved bench") {
66 std::string str1 = "Hi World";
67
68 volatile size_t res = 0;
69 for( size_t i = 0; i < loops; ++i ) {
70 std::string s;
71 const size_t bsz = jau::cfmt::default_string_capacity + 1; // including EOS
72 s.reserve(bsz); // incl. EOS
73 s.resize(bsz - 1); // excl. EOS
74 size_t nchars = std::snprintf(&s[0], bsz, "format_check: '%10s'", str1.c_str());
75 if( nchars < bsz ) {
76 s.resize(nchars);
77 }
78 REQUIRE(format_check_exp == s);
79 res = res + nchars;
80 }
81 return res;
82 };
83}
84
85TEST_CASE("jau_cfmt_benchmark_str2", "[benchmark][jau][std::string][format_string]") {
86 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
87 WARN("Benchmark with " + std::to_string(loops) + " loops");
88 CHECK(true);
89
90 static constexpr const char *format_check_exp = "format_check: 003, ' Hi World'";
91 BENCHMARK("fmt1.32 format rsrved bench") {
92 int i1 = 3;
93 std::string str1 = "Hi World";
94
95 volatile size_t res = 0;
96 for( size_t i = 0; i < loops; ++i ) {
97 std::string s = jau::format_string("format_check: %03d, '%10s'", i1, str1);
98 REQUIRE(format_check_exp == s);
99 res = res + s.size();
100 }
101 return res;
102 };
103 BENCHMARK("fmtX.32 snprintf rsrved bench") {
104 int i1 = 3;
105 std::string str1 = "Hi World";
106
107 volatile size_t res = 0;
108 for( size_t i = 0; i < loops; ++i ) {
109 std::string s;
110 const size_t bsz = jau::cfmt::default_string_capacity + 1; // including EOS
111 s.reserve(bsz); // incl. EOS
112 s.resize(bsz - 1); // excl. EOS
113 size_t nchars = std::snprintf(&s[0], bsz, "format_check: %03d, '%10s'", i1, str1.c_str());
114 if( nchars < bsz ) {
115 s.resize(nchars);
116 }
117 REQUIRE(format_check_exp == s);
118 res = res + nchars;
119 }
120 return res;
121 };
122}
123
124TEST_CASE("jau_cfmt_benchmark_all", "[benchmark][jau][std::string][format_string]") {
125 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
126 WARN("Benchmark with " + std::to_string(loops) + " loops");
127 CHECK(true);
128
129 static constexpr const char *format_check_exp = "format_check: 1.10, 2.20, 1, 2, 003, Hi World";
130
131 BENCHMARK("fmt1.01 check bench") {
132 float fa = 1.1f, fb = 2.2f;
133 size_t sz1 = 1;
134 uint64_t sz2 = 2;
135 int i1 = 3;
136 std::string str1 = "Hi World";
137
138 volatile size_t res = 0;
139 for( size_t i = 0; i < loops; ++i ) {
140 ssize_t r = jau::cfmt::check("format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d, %10s", fa, fb, sz1, sz2, i1, str1);
141 REQUIRE(6 == r);
142 res = res + r;
143 }
144 return res;
145 };
146 BENCHMARK("fmt1.02 checkR bench") {
147 float fa = 1.1f, fb = 2.2f;
148 size_t sz1 = 1;
149 uint64_t sz2 = 2;
150 int i1 = 3;
151 std::string str1 = "Hi World";
152
153 volatile size_t res = 0;
154 for( size_t i = 0; i < loops; ++i ) {
155 jau::cfmt::Result pc = jau::cfmt::checkR("format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d, %10s", fa, fb, sz1, sz2, i1, str1);
156 REQUIRE(6 == pc.argumentCount());
157 res = res + pc.argumentCount();
158 }
159 return res;
160 };
161 BENCHMARK("fmt1.20 format-ckd rsrved bench") {
162 float fa = 1.1f, fb = 2.2f;
163 size_t sz1 = 1;
164 uint64_t sz2 = 2;
165 int i1 = 3;
166 std::string str1 = "Hi World";
167
168 volatile size_t res = 0;
169 for( size_t i = 0; i < loops; ++i ) {
170 std::string s = jau_format_string("format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d, %10s", fa, fb, sz1, sz2, i1, str1);
171 REQUIRE(format_check_exp == s);
172 res = res + s.size();
173 }
174 return res;
175 };
176 BENCHMARK("fmt1.30 formatR rsrved bench") {
177 float fa = 1.1f, fb = 2.2f;
178 size_t sz1 = 1;
179 uint64_t sz2 = 2;
180 int i1 = 3;
181 std::string str1 = "Hi World";
182
183 volatile size_t res = 0;
184 for( size_t i = 0; i < loops; ++i ) {
185 std::string s;
187
188 jau::cfmt::formatR(s, "format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d, %10s", fa, fb, sz1, sz2, i1, str1);
189 REQUIRE(format_check_exp == s);
190 res = res + s.size();
191 }
192 return res;
193 };
194 BENCHMARK("fmt1.32 format rsrved bench") {
195 float fa = 1.1f, fb = 2.2f;
196 size_t sz1 = 1;
197 uint64_t sz2 = 2;
198 int i1 = 3;
199 std::string str1 = "Hi World";
200
201 volatile size_t res = 0;
202 for( size_t i = 0; i < loops; ++i ) {
203 std::string s = jau::format_string("format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d, %10s", fa, fb, sz1, sz2, i1, str1);
204 REQUIRE(format_check_exp == s);
205 res = res + s.size();
206 }
207 return res;
208 };
209 BENCHMARK("fmtX.32 snprintf rsrved bench") {
210 float fa = 1.1f, fb = 2.2f;
211 size_t sz1 = 1;
212 uint64_t sz2 = 2;
213 int i1 = 3;
214 std::string str1 = "Hi World";
215
216 volatile size_t res = 0;
217 for( size_t i = 0; i < loops; ++i ) {
218 std::string s;
219 const size_t bsz = jau::cfmt::default_string_capacity + 1; // including EOS
220 s.reserve(bsz); // incl. EOS
221 s.resize(bsz - 1); // excl. EOS
222 size_t nchars = std::snprintf(&s[0], bsz, "format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d, %10s", fa, fb, sz1, sz2, i1, str1.c_str());
223 if( nchars < bsz ) {
224 s.resize(nchars);
225 }
226 REQUIRE(format_check_exp == s);
227 res = res + nchars;
228 }
229 return res;
230 };
231 BENCHMARK("fmt1.42 format bench") {
232 float fa = 1.1f, fb = 2.2f;
233 size_t sz1 = 1;
234 uint64_t sz2 = 2;
235 int i1 = 3;
236 std::string str1 = "Hi World";
237
238 volatile size_t res = 0;
239 for( size_t i = 0; i < loops; ++i ) {
240 // fa += 0.01f; fb += 0.02f; ++sz1; ++i1; str1.append("X");
241 std::string s = jau::cfmt::format("format_check: %.2f, %2.2f, %zu, %" PRIu64 ", %03d, %10s", fa, fb, sz1, sz2, i1, str1);
242 REQUIRE(format_check_exp == s);
243 res = res + s.size();
244 }
245 return res;
246 };
247 BENCHMARK("fmtX.50 stringstream bench") {
248 float fa = 1.1f, fb = 2.2f;
249 size_t sz1 = 1;
250 uint64_t sz2 = 2;
251 int i1 = 3;
252 std::string str1 = "Hi World";
253
254 volatile size_t res = 0;
255 for( size_t i = 0; i < loops; ++i ) {
256 std::ostringstream ss1;
257 ss1 << "format_check: "
258 << fa << ", "
259 << fb << ", "
260 << sz1 << ", "
261 << sz2 << ", "
262 << i1 << ", "
263 << str1;
264 std::string s = ss1.str();
265 REQUIRE("format_check: 1.1, 2.2, 1, 2, 3, Hi World" == s);
266 res = res + s.size();
267 }
268 return res;
269 };
270#ifdef HAS_STD_FORMAT
271 BENCHMARK("fmtX.60 stdformat bench") {
272 float fa = 1.1f, fb = 2.2f;
273 size_t sz1 = 1;
274 uint64_t sz2 = 2;
275 int i1 = 3;
276 std::string str1 = "Hi World";
277
278 volatile size_t res = 0;
279 for( size_t i = 0; i < loops; ++i ) {
280 std::string s = std::format("format_040b: {0:.2f}, {1:2.2f}, {3}, {4}, {5:03d}, {6:10s}", fa, fb, sz1, sz2, i1, str1);
281 REQUIRE(format_check_exp == s);
282 res = res + s.size();
283 }
284 return res;
285 };
286#endif
287}
288
constexpr ssize_t argumentCount() const noexcept
Arguments processed.
Result formatR(std::string &s, size_t maxLen, std::string_view fmt, const Targs &...args) noexcept
Strict format with type validation of arguments against the format string, appending to the given des...
consteval_cxx20 Result checkR(std::string_view fmt, const Targs &...) noexcept
Strict compile-time type validation of deduced argument-types against the format string.
#define jau_format_string(fmt,...)
Macro, safely returns a (non-truncated) string according to snprintf() formatting rules using a reser...
constexpr const size_t default_string_capacity
Default string reserved capacity w/o EOS (511)
consteval_cxx20 ssize_t check(std::string_view fmt, const Targs &...) noexcept
Strict compile-time type validation of deduced argument-types against the format string.
std::string format(std::string_view fmt, const Targs &...args) noexcept
Strict format with type validation of arguments against the format string.
std::string format_string(std::string_view fmt, const Args &...args) noexcept
Safely returns a (non-truncated) string according to snprintf() formatting rules using a reserved str...
static int loops
TEST_CASE("jau_cfmt_benchmark_str1", "[benchmark][jau][std::string][format_string]")
Execute with test_stringfmt_perf --perf-analysis