Skip to content

Instantly share code, notes, and snippets.

@jcelerier
Created May 6, 2017 10:49
Show Gist options
  • Save jcelerier/59a72cd9f83875f391eaa70eb0904072 to your computer and use it in GitHub Desktop.
Save jcelerier/59a72cd9f83875f391eaa70eb0904072 to your computer and use it in GitHub Desktop.
benchmark of containers
#include <map>
#include <boost/container/flat_map.hpp>
#include <unordered_map>
#include <string>
#include <chrono>
#include <iostream>
#include <vector>
#include <experimental/string_view>
const auto strings = {"token0", "foobar", "bee happy, very happy, very very happy", "", "12345"};
const auto bad_strings = {"0nekot", "oeiqyrgh", "-", "fqsiohaéfhisf", "9887654"};
std::vector<std::experimental::string_view> good_sv{strings.begin(), strings.end()};
std::map<std::string, int> map;
std::unordered_map<std::string, int> unordered_map;
boost::container::flat_map<std::string, int> flat_map;
int if_test(const std::string& s)
{
using namespace std::literals;
if(s == good_sv[0])
return 0;
else if(s == good_sv[1])
return 1;
else if(s == good_sv[2])
return 2;
else if(s == good_sv[3])
return 3;
else if(s == good_sv[4])
return 4;
else
return 5;
}
template<typename T>
void setup_map(T& map)
{
int i = 0;
for(std::string s : strings)
map.insert(std::make_pair(s, i++));
}
template<typename T>
int benchmark_map(const std::string& s, const T& map)
{
auto it = map.find(s);
if(it != map.end())
return it->second;
return 5;
}
struct clk
{
using impl = std::chrono::high_resolution_clock;
impl::time_point m_t0;
clk(): m_t0{impl::now()} {}
~clk() {
using namespace std::chrono;
std::cout
<< duration_cast<milliseconds>(impl::now() - m_t0).count()
<< std::endl;
}
};
int benchmark(const std::vector<std::string>& vec)
{
int r = 0;
std::cout << "With if's: ";
{ clk c;
for(auto& s : vec)
r += if_test(s);
}
std::cout << "std::map: ";
{ clk c;
for(auto& s : vec)
r += benchmark_map(s, map);
}
std::cout << "std::unordered_map: ";
{ clk c;
for(auto& s : vec)
r += benchmark_map(s, unordered_map);
}
std::cout << "boost::flat_map: ";
{ clk c;
for(auto& s : vec)
r += benchmark_map(s, flat_map);
}
return r;
}
const std::string good_string() { return *(strings.begin() + (rand() % strings.size())); }
const std::string bad_string() { return *(bad_strings.begin() + (rand() % bad_strings.size())); }
int main()
{
srand(time(nullptr));
const int N = 1000000;
int r = 0;;
setup_map(map);
setup_map(unordered_map);
setup_map(flat_map);
std::cout << "Good tokens\n";
// Good tokens only benchmark
{
std::vector<std::string> good_tokens;
for(int i = 0; i < N; i++)
{
good_tokens.push_back(good_string());
}
r += benchmark(good_tokens);
}
std::cout << "\nBad tokens\n";
// Bad tokens only benchmark
{
std::vector<std::string> bad_tokens;
for(int i = 0; i < N; i++)
{
bad_tokens.push_back(bad_string());
}
r += benchmark(bad_tokens);
}
// Good and bad tokens
std::cout << "\nMixed tokens\n";
{
std::vector<std::string> mixed_tokens;
for(int i = 0; i < N; i++)
{
bool kind = rand() % 2;
if(kind)
mixed_tokens.push_back(good_string());
else
mixed_tokens.push_back(bad_string());
}
r += benchmark(mixed_tokens);
}
// Only the first token
std::cout << "\nFirst token\n";
{
std::vector<std::string> only_first_token(N, "token0");
r += benchmark(only_first_token);
}
// Only the last token
std::cout << "\nLast token\n";
{
std::vector<std::string> only_last_token(N, "12345");
r += benchmark(only_last_token);
}
std::cout << "total: " << r << "\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment