Created
May 16, 2018 20:14
-
-
Save n0phx/9c6748c653312ef933c4c8eb770bd285 to your computer and use it in GitHub Desktop.
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 <unordered_map> | |
struct EnumClassHash | |
{ | |
template <typename T> | |
std::size_t operator()(T t) const | |
{ | |
return static_cast<std::size_t>(t); | |
} | |
}; | |
struct not_found | |
{ | |
}; | |
template <typename TKey, typename TValue, TKey...> | |
struct JumpTable; | |
template <typename TKey, typename TValue> | |
struct JumpTable<TKey, TValue> | |
{ | |
TValue& operator[]([[maybe_unused]] TKey needed) | |
{ | |
throw not_found{}; | |
} | |
}; | |
template <typename TKey, typename TValue, TKey key, TKey... rest> | |
struct JumpTable<TKey, TValue, key, rest...> : JumpTable<TKey, TValue, rest...> | |
{ | |
TValue value; | |
using super = JumpTable<TKey, TValue, rest...>; | |
TValue& operator[](TKey k) | |
{ | |
return key == k ? value : super::operator[](k); | |
} | |
}; | |
enum class DispatchId | |
{ | |
Id1 = 10, | |
Id2 = 20, | |
Id3 = 30 | |
}; | |
using FuncType = int (*)(int); | |
class Dispatcher | |
{ | |
private: | |
FuncType m_fn1; | |
FuncType m_fn2; | |
FuncType m_fn3; | |
public: | |
FuncType& find(DispatchId id) | |
{ | |
switch (id) | |
{ | |
case DispatchId::Id1: | |
return m_fn1; | |
case DispatchId::Id2: | |
return m_fn2; | |
case DispatchId::Id3: | |
return m_fn3; | |
default: | |
throw not_found{}; | |
} | |
} | |
}; | |
int fn1(int x) | |
{ | |
return x + 1; | |
} | |
int fn2(int x) | |
{ | |
return x + 2; | |
} | |
int fn3(int x) | |
{ | |
return x + 3; | |
} | |
static void UnorderedMapDispatch(benchmark::State& state) | |
{ | |
std::unordered_map<DispatchId, FuncType, EnumClassHash> dm; | |
dm.insert({DispatchId::Id1, fn1}); | |
dm.insert({DispatchId::Id2, fn2}); | |
dm.insert({DispatchId::Id3, fn3}); | |
for (auto _ : state) | |
{ | |
dm.at(static_cast<DispatchId>(state.range(0)))(state.range(0)); | |
} | |
} | |
BENCHMARK(UnorderedMapDispatch)->Arg(10)->Arg(20)->Arg(30); | |
static void SwitchDispatch(benchmark::State& state) | |
{ | |
Dispatcher d; | |
d.find(DispatchId::Id1) = fn1; | |
d.find(DispatchId::Id2) = fn2; | |
d.find(DispatchId::Id3) = fn3; | |
for (auto _ : state) | |
{ | |
d.find(static_cast<DispatchId>(state.range(0)))(state.range(0)); | |
} | |
} | |
BENCHMARK(SwitchDispatch)->Arg(10)->Arg(20)->Arg(30); | |
static void JumpTableDispatch(benchmark::State& state) | |
{ | |
JumpTable<DispatchId, FuncType, DispatchId::Id1, DispatchId::Id2, DispatchId::Id3> jt; | |
jt[DispatchId::Id1] = fn1; | |
jt[DispatchId::Id2] = fn2; | |
jt[DispatchId::Id3] = fn3; | |
for (auto _ : state) | |
{ | |
jt[static_cast<DispatchId>(state.range(0))](state.range(0)); | |
} | |
} | |
BENCHMARK(JumpTableDispatch)->Arg(10)->Arg(20)->Arg(30); | |
BENCHMARK_MAIN(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment