Skip to content

Commit c333c22

Browse files
committed
Add benchmark utility.
1 parent ac61242 commit c333c22

File tree

12 files changed

+306
-488
lines changed

12 files changed

+306
-488
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,4 @@ tests/data/GB18030-2022.TXT
8989
tests/tmp-*.TXT
9090
*.tmp
9191
*.dump
92+
benchmark/benchmark

CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ install(FILES "${output_includedir}/cppp/reiconv.hpp.inst"
124124

125125
# PERMISSIONS 0644
126126
install(FILES "${output_includedir}/cppp/encodings/reiconv.hpp"
127-
DESTINATION "${install_includedir}/encodings"
128-
RENAME "cppp/reiconv.hpp"
127+
DESTINATION "${install_includedir}"
128+
RENAME "cppp/encodings/reiconv.hpp"
129129
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ )
130130

131131
# PERMISSIONS 0644
@@ -136,8 +136,8 @@ install(FILES "${output_includedir}/cppp/reiconv.h.inst"
136136

137137
# PERMISSIONS 0644
138138
install(FILES "${output_includedir}/cppp/encodings/reiconv.h"
139-
DESTINATION "${install_includedir}/encodings"
140-
RENAME "cppp/reiconv.h"
139+
DESTINATION "${install_includedir}"
140+
RENAME "cppp/encodings/reiconv.h"
141141
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ )
142142

143143
# PERMISSIONS 0644

benchmark/benchmark.cpp

Lines changed: 64 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -1,220 +1,112 @@
11
#include "benchmark.hpp"
2-
#include "test_string.hpp"
3-
2+
#include "cppp/reiconv.h"
43
#include <benchmark/benchmark.h>
5-
#include <cppp/reiconv.hpp>
6-
#include <cppp/reiconv.h>
74
#include <unicode/ucnv.h>
85

9-
#include <cstddef>
10-
#include <stdexcept>
11-
12-
13-
static void reiconv_handle_open_by_name(benchmark::State& state)
14-
{
15-
for (auto _: state)
16-
{
17-
volatile reiconv::Encoding index = {"UTF-8"};
18-
volatile reiconv::Encoding index2 = {"CP936"};
19-
}
20-
}
6+
#include <cctype>
7+
#include <cstring>
8+
#include <string_view>
219

22-
BENCHMARK(reiconv_handle_open_by_name);
10+
char *test_string_utf8;
11+
std::size_t test_string_utf8_len;
2312

24-
static void reiconv_handle_open_by_codepage(benchmark::State& state)
13+
static void reiconv(benchmark::State &state)
2514
{
26-
for (auto _: state)
15+
char output[test_string_utf8_len * 4];
16+
void *cd = reiconv_iconv_open();
17+
for (auto _ : state)
2718
{
28-
volatile reiconv::Encoding index = {65001};
29-
volatile reiconv::Encoding index2 = {936};
19+
reiconv_convert_static_size(cd, test_string_utf8, test_string_utf8_len, output, test_string_utf8_len * 4);
3020
}
3121
}
22+
BENCHMARK(reiconv);
3223

33-
BENCHMARK(reiconv_handle_open_by_codepage);
34-
35-
static void reiconv_handle_open_by_index(benchmark::State& state)
24+
static void glibc(benchmark::State &state)
3625
{
37-
for (auto _: state)
26+
char output[test_string_utf8_len * 4];
27+
void *cd = glibc_iconv_open();
28+
for (auto _ : state)
3829
{
39-
volatile reiconv::Encoding index = {reiconv::Encodings::UTF8};
40-
volatile reiconv::Encoding index2 = {reiconv::Encodings::CP936};
30+
glibc_static_size_convert(cd, test_string_utf8, test_string_utf8_len, output, test_string_utf8_len * 4);
4131
}
4232
}
33+
BENCHMARK(glibc);
4334

44-
BENCHMARK(reiconv_handle_open_by_index);
45-
46-
static void glibc_iconv_dynamic_length(benchmark::State& state)
35+
static void libiconv(benchmark::State &state)
4736
{
48-
char* output = nullptr;
49-
std::size_t length = 0;
50-
51-
for (auto _: state)
37+
char output[test_string_utf8_len * 4];
38+
void *cd = libiconv_iconv_open();
39+
for (auto _ : state)
5240
{
53-
output = nullptr;
54-
length = 0;
55-
glibc_iconv_string("GB18030", "UTF-8", simple_test_string_utf8, simple_test_string_utf8 + 1, &output, &length);
56-
free(output);
41+
libiconv_static_size_convert(cd, test_string_utf8, test_string_utf8_len, output, test_string_utf8_len * 4);
5742
}
5843
}
44+
BENCHMARK(libiconv);
5945

60-
BENCHMARK(glibc_iconv_dynamic_length);
61-
62-
static void libiconv_iconv_dynamic_length(benchmark::State& state)
46+
static void libicu(benchmark::State &state)
6347
{
64-
char* output = nullptr;
65-
std::size_t length = 0;
48+
UErrorCode status{U_ZERO_ERROR};
49+
char output[test_string_utf8_len * 4];
6650

67-
for (auto _: state)
51+
for (auto _ : state)
6852
{
69-
output = nullptr;
70-
length = 0;
71-
libiconv_iconv_string("GB18030", "UTF-8", simple_test_string_utf8, simple_test_string_utf8 + 1, &output, &length);
72-
free(output);
53+
ucnv_convert("GB18030", "UTF-8", output, test_string_utf8_len * 4, test_string_utf8, test_string_utf8_len,
54+
&status);
7355
}
7456
}
57+
BENCHMARK(libicu);
7558

76-
BENCHMARK(libiconv_iconv_dynamic_length);
77-
78-
static void glibc_iconv_static_length(benchmark::State& state)
59+
void init_test_string(std::size_t len)
7960
{
80-
char* output = nullptr;
81-
std::size_t length = 0;
82-
glibc_static_size_convert("GB18030", "UTF-8", simple_test_string_utf8, 1, &output, length);
83-
free(output);
84-
85-
for (auto _: state)
61+
constexpr const char *const test_string =
62+
"\u6211\u80fd\u541e\u4e0b\u8eab\u4f53\u800c\u4e0d\u4f24\u8eab\u4f53\u30021234567890ABCD";
63+
constexpr const std::size_t test_string_len = 50;
64+
test_string_utf8 = new char[test_string_len * len];
65+
test_string_utf8_len = test_string_len * len;
66+
for (std::size_t i = 0; i < len; ++i)
8667
{
87-
output = nullptr;
88-
length = 0;
89-
glibc_static_size_convert("GB18030", "UTF-8", simple_test_string_utf8, 1, &output, length);
90-
free(output);
68+
std::memcpy(test_string_utf8 + i * test_string_len, test_string, test_string_len);
9169
}
9270
}
9371

94-
static void libiconv_static_length(benchmark::State& state)
72+
static inline bool isdigit(const std::string_view str)
9573
{
96-
char* output = nullptr;
97-
std::size_t length = 0;
98-
libiconv_static_size_convert("GB18030", "UTF-8", simple_test_string_utf8, 1, &output, length);
99-
free(output);
100-
101-
for (auto _: state)
74+
for (const char c : str)
10275
{
103-
output = nullptr;
104-
length = 0;
105-
libiconv_static_size_convert("GB18030", "UTF-8", simple_test_string_utf8, 1, &output, length);
106-
free(output);
76+
if (!std::isdigit(c))
77+
{
78+
return false;
79+
}
10780
}
81+
return true;
10882
}
10983

110-
static void libicu_static_length(benchmark::State& state)
84+
const char *const_argv_default[2] = {"benchmark", "--benchmark_format=json"};
85+
int main(int argc, char **argv)
11186
{
112-
UErrorCode status{ U_ZERO_ERROR };
113-
size_t enough_size = 24;
114-
char* output = (char*)malloc(enough_size);
115-
memset(output, 0, enough_size);
116-
int len = ucnv_convert("GB18030",
117-
"UTF-8",
118-
output,
119-
enough_size,
120-
simple_test_string_utf8,
121-
1,
122-
&status);
123-
124-
if (U_FAILURE(status))
87+
if (argc != 2)
12588
{
126-
free(output);
127-
throw std::runtime_error("ucnv_convert failed");
89+
std::fputs("Usage: benchmark <test_string_repeat_times>\n", stderr);
90+
return EXIT_FAILURE;
12891
}
129-
free(output);
130-
131-
for (auto _: state)
92+
if (!isdigit(argv[1]))
13293
{
133-
output = (char*)malloc(enough_size);
134-
memset(output, 0, enough_size);
135-
len = ucnv_convert("GB18030",
136-
NULL,
137-
output,
138-
enough_size,
139-
simple_test_string_utf8,
140-
1,
141-
&status);
142-
free(output);
94+
std::fputs("Error: test_string_repeat_times must be a number.\n", stderr);
95+
return EXIT_FAILURE;
14396
}
144-
}
145-
146-
BENCHMARK(libicu_static_length);
147-
14897

98+
std::size_t len = std::atoi(argv[1]);
99+
init_test_string(len);
149100

150-
constexpr std::size_t big_test_string_utf8_len = sizeof(big_test_string_utf8) - 1;
151-
152-
static void reiconv_convert(benchmark::State& state)
153-
{
154-
using namespace reiconv;
155-
for (auto _: state)
101+
int argc_default = 2;
102+
::benchmark::Initialize(&argc_default, const_cast<char **>(const_argv_default));
103+
if (::benchmark::ReportUnrecognizedArguments(argc_default, const_cast<char **>(const_argv_default)))
156104
{
157-
reiconv_t cd = reiconv_open_from_index(reiconv_lookup_from_name("UTF-8"), reiconv_lookup_from_name("GB18030"), false);
158-
char* output = nullptr;
159-
size_t length = 0;
160-
reiconv_convert(cd, big_test_string_utf8, big_test_string_utf8_len, &output, &length);
161-
free(output);
105+
return EXIT_FAILURE;
162106
}
163-
}
164-
165-
BENCHMARK(reiconv_convert);
107+
::benchmark::RunSpecifiedBenchmarks();
108+
::benchmark::Shutdown();
166109

167-
static void glibc_convert(benchmark::State& state)
168-
{
169-
char* output = nullptr;
170-
std::size_t length = 0;
171-
for (auto _: state)
172-
{
173-
output = nullptr;
174-
length = 0;
175-
glibc_iconv_string("GB18030", "UTF-8", big_test_string_utf8, big_test_string_utf8 + big_test_string_utf8_len, &output, &length);
176-
free(output);
177-
}
110+
delete[] test_string_utf8; // Not necessary.
111+
return EXIT_SUCCESS;
178112
}
179-
180-
BENCHMARK(glibc_convert);
181-
182-
static void libiconv_convert(benchmark::State& state)
183-
{
184-
char* output = nullptr;
185-
std::size_t length = 0;
186-
for (auto _: state)
187-
{
188-
output = nullptr;
189-
length = 0;
190-
libiconv_iconv_string("GB18030", "UTF-8", big_test_string_utf8, big_test_string_utf8 + big_test_string_utf8_len, &output, &length);
191-
free(output);
192-
}
193-
}
194-
195-
BENCHMARK(libiconv_convert);
196-
197-
static void libicu_convert(benchmark::State& state)
198-
{
199-
UErrorCode status{ U_ZERO_ERROR };
200-
size_t enough_size = big_test_string_utf8_len * 4;
201-
char* output = nullptr;
202-
for (auto _: state)
203-
{
204-
output = (char*)malloc(enough_size);
205-
memset(output, 0, enough_size);
206-
207-
ucnv_convert_72("GB18030",
208-
NULL,
209-
output,
210-
enough_size + 1,
211-
big_test_string_utf8,
212-
big_test_string_utf8_len,
213-
&status);
214-
free(output);
215-
}
216-
}
217-
218-
BENCHMARK(libicu_convert);
219-
220-
BENCHMARK_MAIN();

benchmark/benchmark.hpp

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,14 @@
44

55
#include <cstddef>
66

7-
extern int glibc_iconv_string(const char* tocode,
8-
const char* fromcode,
9-
const char* start,
10-
const char* end,
11-
char** resultp,
12-
std::size_t* lengthp);
7+
extern void* glibc_iconv_open();
8+
extern int glibc_static_size_convert(void* cd, const char *input_data, size_t input_length, char *output_data,
9+
size_t output_length);
1310

14-
extern void glibc_static_size_convert(const char* tocode,
15-
const char* fromcode,
16-
const char* data,
17-
std::size_t size,
18-
char** resultp,
19-
std::size_t result_size);
11+
extern void* libiconv_iconv_open();
12+
extern int libiconv_static_size_convert(void* cd, const char *input_data, size_t input_length, char *output_data,
13+
size_t output_length);
2014

21-
extern int libiconv_iconv_string(const char* tocode,
22-
const char* fromcode,
23-
const char* start,
24-
const char* end,
25-
char** resultp,
26-
std::size_t* lengthp);
27-
28-
extern void libiconv_static_size_convert(const char* tocode,
29-
const char* fromcode,
30-
const char* data,
31-
std::size_t size,
32-
char** resultp,
33-
std::size_t result_size);
15+
extern void* reiconv_iconv_open();
16+
extern int reiconv_static_size_convert(void* cd, const char *input_data, size_t input_length, char *output_data,
17+
size_t output_length); // Unused.

benchmark/benchmark.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Benchmark
2+
3+
## Compile command
4+
5+
```bash
6+
cd benchmark
7+
g++ *.cpp -I/tmp/inst/include /tmp/inst/lib/libicudata.a /tmp/inst/lib/libicuuc.a /tmp/inst/lib/libiconv.a /tmp/inst/lib/libcharset.a /tmp/inst/lib/libcppp-reiconv.static.a /usr/local/lib/libbenchmark.a /tmp/inst/lib/*.a -O2 -fPIC -Wall -o benchmark
8+
```
9+
10+
## GCC version
11+
12+
```text
13+
gcc (Debian 14.2.0-8) 14.2.0
14+
```
15+
16+
## Benchmark result
17+
18+
![benchmark result](./benchmark.png)

benchmark/benchmark.png

105 KB
Loading

0 commit comments

Comments
 (0)