1 #include <marnav/nmea/split.hpp>
2 #include <benchmark/benchmark.h>
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 "$,,,,,,,,,,,,*",
15 // Baseline implementation.
16 static std::vector
<std::string
> parse_fields_v0(const std::string
& s
)
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
)
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
)
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
)
54 p
= s
.find_first_of(DELIMITERS
, last
);
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
)
64 return std::vector
<std::string
>{};
66 static const char * DELIMITERS
= ",*";
67 std::vector
<std::string
> result
;
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
)
76 p
= s
.find_first_of(DELIMITERS
, last
);
81 static std::vector
<std::string
> parse_fields_v4(const std::string
& s
)
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;
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
);
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);