jaulib v1.4.1-17-gd77ace3-dirty
Jau Support Library (C++, Java, ..)
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
138 BENCHMARK("append_integral rsrved bench") {
139 volatile size_t res = 0;
140 for( size_t i = 0; i < loops; ++i ) {
141 std::string s;
143
144 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
145 REQUIRE(format_check_exp == s);
146 res = res + s.size();
147 }
148 return res;
149 };
150
151 BENCHMARK("snprintf rsrved bench") {
152 volatile size_t res = 0;
153 for( size_t i = 0; i < loops; ++i ) {
154 std::string s;
155 const size_t bsz = jau::cfmt::default_string_capacity + 1; // including EOS
156 s.reserve(bsz); // incl. EOS
157 s.resize(bsz - 1); // excl. EOS
158 size_t nchars = std::snprintf(&s[0], bsz, "%zu", i1);
159 if( nchars < bsz ) {
160 s.resize(nchars);
161 }
162 REQUIRE(format_check_exp == s);
163 res = res + nchars;
164 }
165 return res;
166 };
167}
168
169TEST_CASE("jau_cfmt_benchmark_append_integral01", "[benchmark][jau][std::string][format_string]") {
170 const size_t loops = 1000; // catch_auto_run ? 1000 : 1000;
171 WARN("Benchmark with " + std::to_string(loops) + " loops");
172 CHECK(true);
173
174 const uint64_t i1 = std::numeric_limits<uint64_t>::max(); // Value = 18446744073709551615 (0xffffffffffffffff)
175 static constexpr const char *format_check_exp1 = " 0000000018'446'744'073'709'551'615";
176 static constexpr const char *format_check_exp0 = " 0000000000000018446744073709551615";
179 o1.addFlag('\'');
180 o1.setWidth(38);
181 o1.setPrecision(34);
182 o1.setConversion('u');
183 std::cout << "flags: " << o1 << "\n";
184
185 {
186 std::string s;
188
189 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
190 REQUIRE(format_check_exp1 == s);
191 }
192
193 BENCHMARK("append_integral rsrved bench") {
194 volatile size_t res = 0;
195 for( size_t i = 0; i < loops; ++i ) {
196 std::string s;
198
199 jau::cfmt::impl::append_integral(s, s.max_size(), i1, false, o1, false);
200 REQUIRE(format_check_exp1 == s);
201 res = res + s.size();
202 }
203 return res;
204 };
205
206 BENCHMARK("snprintf rsrved bench") {
207 volatile size_t res = 0;
208 for( size_t i = 0; i < loops; ++i ) {
209 std::string s;
210 const size_t bsz = jau::cfmt::default_string_capacity + 1; // including EOS
211 s.reserve(bsz); // incl. EOS
212 s.resize(bsz - 1); // excl. EOS
213 size_t nchars = std::snprintf(&s[0], bsz, "%38.34zu", i1);
214 if( nchars < bsz ) {
215 s.resize(nchars);
216 }
217 REQUIRE(format_check_exp0 == s);
218 res = res + nchars;
219 }
220 return res;
221 };
222}
constexpr const size_t default_string_capacity
Default string reserved capacity w/o EOS (511)
@ z
size_t or ssize_t integer
void append_integral(std::string &dest, const size_t dest_maxlen, uint64_t v, const bool negative, const FormatOpts &opts, const bool inject_dot=false)
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]")