$ clang++ bm_split.cpp -lbenchmark -pthread -O3 && ./a.out
2020-03-20 19:35:24
Running ./a.out
Run on (4 X 2800 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x4)
L1 Instruction 32 KiB (x4)
L2 Unified 256 KiB (x4)
L3 Unified 6144 KiB (x1)
Load Average: 0.55, 0.68, 0.66
---------------------------------------------------------------------
Benchmark Time CPU Iterations
---------------------------------------------------------------------
bm_split_manual 82.4 ns 82.1 ns 8487012
bm_split_with_stringstream 781 ns 778 ns 922450
Last active
March 20, 2020 18:04
-
-
Save tshev/7994cb2b0360e2d1a605b949775bc44d to your computer and use it in GitHub Desktop.
Benchmark split
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <benchmark/benchmark.h> | |
#include <iostream> | |
#include <vector> | |
#include <algorithm> | |
#include <sstream> | |
static void escape(void* ptr) { | |
asm volatile("" : : "g"(ptr) : "memory"); | |
} | |
bool ignore_character(char x) { | |
return x == ' ' || x == '\t' || x == '\n' || x == '\t'; | |
} | |
template<typename It0, typename Out, typename F, typename P> | |
Out split(It0 first, It0 last, Out out, F f, P p) { | |
while (first != last) { | |
auto middle = std::find_if(first, last, [](auto x) { return ignore_character(x); }); | |
if (p(first, middle)) { | |
out = f(first, middle); | |
++out; | |
} | |
if (middle != last) ++middle; | |
first = middle; | |
} | |
return out; | |
} | |
std::vector<std::string> split_manual(const std::string& s) { | |
std::vector<std::string> words; | |
words.reserve(std::count_if(s.begin(), s.end(), ignore_character) + 1ul); | |
split(std::begin(s), std::end(s), std::back_inserter(words), [](auto first, auto last) { return std::string(first, last); }, [](auto first, auto _) { return !ignore_character(*first); }); | |
return words; | |
} | |
std::vector<std::string> split_with_string_stream(const std::string& s) { | |
std::stringstream stream; | |
stream << s; | |
std::vector<std::string> words; | |
words.reserve(std::count_if(s.begin(), s.end(), ignore_character) + 1ul); | |
std::string buffer; | |
while (stream) { | |
stream >> buffer; | |
if (!buffer.empty()) | |
words.emplace_back(std::move(buffer)); | |
} | |
return words; | |
} | |
static void bm_split_manual(benchmark::State& state) { | |
std::string data = "good morning to you"; | |
for (auto _ : state) { | |
auto words = split_manual(data); | |
escape(&words); | |
} | |
auto words = split_manual(data); | |
assert(words.size() == 4); | |
assert(words[0] == "good"); | |
assert(words[1] == "morning"); | |
assert(words[2] == "to"); | |
assert(words[3] == "you"); | |
} | |
static void bm_split_with_stringstream(benchmark::State& state) { | |
std::string data = "good morning to you"; | |
for (auto _ : state) { | |
auto words = split_with_string_stream(data); | |
escape(&words); | |
} | |
auto words = split_with_string_stream(data); | |
assert(words.size() == 4); | |
assert(words[0] == "good"); | |
assert(words[1] == "morning"); | |
assert(words[2] == "to"); | |
assert(words[3] == "you"); | |
} | |
BENCHMARK(bm_split_manual); | |
BENCHMARK(bm_split_with_stringstream); | |
BENCHMARK_MAIN(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment