General: separation of marav-io as a library
[marnav.git] / test / marnav / nmea / Benchmark_nmea_split.cpp
blob7d4ddefe72de94eaaacaa88d2bce4f1e8f55d2d7
1 #include <marnav/nmea/split.hpp>
2 #include <benchmark/benchmark.h>
3 #include <regex>
5 namespace
7 // clang-format off
8 static const std::vector<std::string> SENTENCES = {
9 "$GPRMC,201126,A,4702.3944,N,00818.3381,E,0.0,328.4,260807,0.6,E,A*1E",
10 "$GPRMC,,V,,,,,,,300510,0.6,E,N*39",
11 "$,,,,,,,,,,,,*",
13 // clang-format on
15 // Baseline implementation.
16 static std::vector<std::string> parse_fields_v0(const std::string & s)
18 if (s.size() < 1)
19 return std::vector<std::string>{};
21 std::regex field_regex{"(,|\\*)"};
22 auto fields_begin = std::sregex_token_iterator{begin(s) + 1, end(s), field_regex, -1};
23 auto fields_end = std::sregex_token_iterator();
24 return {fields_begin, fields_end};
27 // Improved implementation, reducing instantiation of regex parser.
28 static std::vector<std::string> parse_fields_v1(const std::string & s)
30 if (s.size() < 1)
31 return std::vector<std::string>{};
33 static const std::regex field_regex{"(,|\\*)"};
34 auto fields_begin = std::sregex_token_iterator{begin(s) + 1, end(s), field_regex, -1};
35 auto fields_end = std::sregex_token_iterator();
36 return {fields_begin, fields_end};
39 // No regex anymore, simple string handling
40 static std::vector<std::string> parse_fields_v2(const std::string & s)
42 if (s.size() < 1)
43 return std::vector<std::string>{};
45 static const char * DELIMITERS = ",*";
46 std::vector<std::string> result;
47 std::string::size_type last = 1;
48 std::string::size_type p = s.find_first_of(DELIMITERS, last);
49 while (last != std::string::npos) {
50 result.push_back(s.substr(last, p - last));
51 if (p == std::string::npos)
52 break;
53 last = p + 1;
54 p = s.find_first_of(DELIMITERS, last);
56 return result;
59 // No regex anymore, simple string handling, reallocating string vector for
60 // 14 elements (number of fields in RMC)
61 static std::vector<std::string> parse_fields_v3(const std::string & s)
63 if (s.size() < 1)
64 return std::vector<std::string>{};
66 static const char * DELIMITERS = ",*";
67 std::vector<std::string> result;
68 result.reserve(14);
69 std::string::size_type last = 1;
70 std::string::size_type p = s.find_first_of(DELIMITERS, last);
71 while (last != std::string::npos) {
72 result.push_back(s.substr(last, p - last));
73 if (p == std::string::npos)
74 break;
75 last = p + 1;
76 p = s.find_first_of(DELIMITERS, last);
78 return result;
81 static std::vector<std::string> parse_fields_v4(const std::string & s)
83 if (s.size() < 1)
84 return std::vector<std::string>{};
86 static constexpr const char * DELIMITERS = ",*";
87 std::vector<std::string> result;
88 result.reserve(14); // number of fields in RMC, fairly common case
89 std::string::size_type p = 0u;
90 do {
91 const auto last = p + 1;
92 p = s.find_first_of(DELIMITERS, last);
93 result.push_back(s.substr(last, p - last));
94 } while (p != std::string::npos);
95 return result;
99 static void Benchmark_nmea_split_v0(benchmark::State & state)
101 std::string sentence = SENTENCES[state.range(0)];
102 std::vector<std::string> result;
103 while (state.KeepRunning()) {
104 result = parse_fields_v0(sentence);
105 benchmark::DoNotOptimize(result);
109 BENCHMARK(Benchmark_nmea_split_v0)->Range(0, 2);
111 static void Benchmark_nmea_split_v1(benchmark::State & state)
113 std::string sentence = SENTENCES[state.range(0)];
114 std::vector<std::string> result;
115 while (state.KeepRunning()) {
116 result = parse_fields_v1(sentence);
117 benchmark::DoNotOptimize(result);
121 BENCHMARK(Benchmark_nmea_split_v1)->Range(0, 2);
123 static void Benchmark_nmea_split_v2(benchmark::State & state)
125 std::string sentence = SENTENCES[state.range(0)];
126 std::vector<std::string> result;
127 while (state.KeepRunning()) {
128 result = parse_fields_v2(sentence);
129 benchmark::DoNotOptimize(result);
133 BENCHMARK(Benchmark_nmea_split_v2)->Range(0, 2);
135 static void Benchmark_nmea_split_v3(benchmark::State & state)
137 std::string sentence = SENTENCES[state.range(0)];
138 std::vector<std::string> result;
139 while (state.KeepRunning()) {
140 result = parse_fields_v3(sentence);
141 benchmark::DoNotOptimize(result);
145 BENCHMARK(Benchmark_nmea_split_v3)->Range(0, 2);
147 static void Benchmark_nmea_split_v4(benchmark::State & state)
149 std::string sentence = SENTENCES[state.range(0)];
150 std::vector<std::string> result;
151 while (state.KeepRunning()) {
152 result = parse_fields_v4(sentence);
153 benchmark::DoNotOptimize(result);
157 BENCHMARK(Benchmark_nmea_split_v4)->Range(0, 2);
159 static void Benchmark_nmea_split(benchmark::State & state)
161 std::string sentence = SENTENCES[state.range(0)];
162 std::vector<std::string> result;
163 while (state.KeepRunning()) {
164 result = marnav::nmea::detail::parse_fields(sentence);
165 benchmark::DoNotOptimize(result);
169 BENCHMARK(Benchmark_nmea_split)->Range(0, 2);
171 BENCHMARK_MAIN();