Skip to content

Instantly share code, notes, and snippets.

@tshev
Last active March 20, 2020 18:04
Show Gist options
  • Save tshev/7994cb2b0360e2d1a605b949775bc44d to your computer and use it in GitHub Desktop.
Save tshev/7994cb2b0360e2d1a605b949775bc44d to your computer and use it in GitHub Desktop.
Benchmark split
$ 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
#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