aboutsummaryrefslogtreecommitdiffstats
path: root/test/bench_bitvec.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-08-26 23:16:00 +0200
committerDavid Robillard <d@drobilla.net>2018-09-29 14:50:34 +0200
commit0a5a45ff8ae437ddf1c3b8de425f30a44e6f5580 (patch)
tree870b40f80575969ab5bb7771d62ecb0bdf13662a /test/bench_bitvec.cpp
parenta115beb0d3fedbe3d286ad1ba2dd7af319f7968d (diff)
downloadchilbert-0a5a45ff8ae437ddf1c3b8de425f30a44e6f5580.tar.gz
chilbert-0a5a45ff8ae437ddf1c3b8de425f30a44e6f5580.tar.bz2
chilbert-0a5a45ff8ae437ddf1c3b8de425f30a44e6f5580.zip
Add benchmarks
Diffstat (limited to 'test/bench_bitvec.cpp')
-rw-r--r--test/bench_bitvec.cpp339
1 files changed, 339 insertions, 0 deletions
diff --git a/test/bench_bitvec.cpp b/test/bench_bitvec.cpp
new file mode 100644
index 0000000..741b2d2
--- /dev/null
+++ b/test/bench_bitvec.cpp
@@ -0,0 +1,339 @@
+/*
+ Copyright (C) 2018 David Robillard <d@drobilla.net>
+
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "bench_utils.hpp"
+
+#include "chilbert/BoundedBitVec.hpp"
+#include "chilbert/DynamicBitVec.hpp"
+#include "chilbert/SmallBitVec.hpp"
+#include "chilbert/StaticBitVec.hpp"
+
+#include <fstream>
+
+template <class T, size_t N>
+struct BenchAnd
+{
+ Duration operator()(Context& ctx)
+ {
+ const T v = make_random_bitvec<T, N>(ctx);
+ T r = make_random_bitvec<T, N>(ctx);
+
+ return run_bench([&](auto) { r &= v; });
+ }
+};
+
+template <class T, size_t N>
+struct BenchOr
+{
+ Duration operator()(Context& ctx)
+ {
+ const T v = make_random_bitvec<T, N>(ctx);
+ T r = make_random_bitvec<T, N>(ctx);
+
+ return run_bench([&](auto) { r |= v; });
+ }
+};
+
+template <class T, size_t N>
+struct BenchXor
+{
+ Duration operator()(Context& ctx)
+ {
+ const T v = make_random_bitvec<T, N>(ctx);
+ T r = make_random_bitvec<T, N>(ctx);
+
+ return run_bench([&](auto) { r ^= v; });
+ }
+};
+
+template <class T, size_t N>
+struct BenchSetOne
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ return run_bench([&](const auto i) { v.set(i % N); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchSetAll
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ return run_bench([&](auto) { v.set(); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchResetOne
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ return run_bench([&](const auto i) { v.reset(i % N); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchResetAll
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ return run_bench([&](auto) { v.reset(); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchFlipOne
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ return run_bench([&](const auto i) { v.flip(i % N); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchFlipAll
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ return run_bench([&](auto) { v.flip(); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchNone
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ bool r = false;
+ return run_bench([&](auto) { r = v.none(); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchCount
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ volatile size_t r = 0;
+ return run_bench([&](auto) { r = v.count(); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchLeftShift
+{
+ Duration operator()(Context& ctx)
+ {
+ const T v = make_random_bitvec<T, N>(ctx);
+ T r = v;
+ return run_bench([&](const auto i) { r <<= (i % N); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchRightShift
+{
+ Duration operator()(Context& ctx)
+ {
+ const T v = make_random_bitvec<T, N>(ctx);
+ T r = v;
+ return run_bench([&](const auto i) { r >>= (i % N); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchLeftRotate
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ return run_bench([&](const auto i) { v.rotl(i % N); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchRightRotate
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ volatile bool r = false;
+ return run_bench([&](const auto i) {
+ v.rotr(i % N);
+ r = v.test(0);
+ });
+ }
+};
+
+template <class T, size_t N>
+struct BenchFindFirst
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ volatile size_t r = 0;
+ return run_bench([&](auto) { r = v.find_first(); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchGrayCode
+{
+ Duration operator()(Context& ctx)
+ {
+ const T v = make_random_bitvec<T, N>(ctx);
+ T r = v;
+
+ return run_bench([&](auto) { chilbert::detail::gray_code(r); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchGrayCodeInv
+{
+ Duration operator()(Context& ctx)
+ {
+ const T v = make_random_bitvec<T, N>(ctx);
+ T r = v;
+
+ return run_bench([&](auto) { chilbert::detail::gray_code_inv(r); });
+ }
+};
+
+template <class T, size_t N>
+struct BenchComparison
+{
+ Duration operator()(Context& ctx)
+ {
+ std::vector<T> vecs;
+ for (size_t i = 0; i < 32; ++i) {
+ vecs.emplace_back(make_random_bitvec<T, N>(ctx));
+ }
+
+ volatile bool r = false;
+
+ return run_bench([&](const auto i) {
+ r |= vecs[i % vecs.size()] < vecs[(i + 1) % vecs.size()];
+ });
+ }
+};
+
+template <class T, size_t N>
+struct BenchIteration
+{
+ Duration operator()(Context& ctx)
+ {
+ T v = make_random_bitvec<T, N>(ctx);
+ auto i = v.begin();
+ volatile bool r = false;
+ return run_bench([&](const auto) {
+ r = (++i == v.end());
+ if (r) {
+ i = v.begin();
+ }
+ });
+ }
+};
+
+/// Run benchmark for size N
+template <template <class U, size_t M> class Bench, size_t N>
+void
+bench_row(Context& ctx, std::ostream& os)
+{
+ std::array<Duration, 4> results = {
+ ((N <= chilbert::SmallBitVec::bits_per_rack)
+ ? Bench<chilbert::SmallBitVec, N>{}(ctx)
+ : Duration{}),
+ Bench<chilbert::StaticBitVec<N>, N>{}(ctx),
+ Bench<chilbert::BoundedBitVec<N>, N>{}(ctx),
+ Bench<chilbert::DynamicBitVec, N>{}(ctx),
+ };
+
+ write_row(os, N, results);
+}
+
+/// Terminate recursion
+template <template <class U, size_t M> class Bench>
+void
+bench_rec(Context&, std::ostream&)
+{
+}
+
+/// Run benchmark for sizes N, Ns... (recursive helper)
+template <template <class U, size_t M> class Bench, size_t N, size_t... Ns>
+void
+bench_rec(Context& ctx, std::ostream& os)
+{
+ bench_row<Bench, N>(ctx, os);
+ bench_rec<Bench, Ns...>(ctx, os);
+}
+
+/// Run benchmark
+template <template <class U, size_t M> class Bench>
+void
+bench(Context& ctx, const std::string& name)
+{
+ std::ofstream out("bitvec_" + name + ".txt");
+ out << "n\tsmall\tstatic\tbounded\tdynamic\n";
+ bench_rec<Bench, 16, 32, 64, 128, 256, 512>(ctx, out);
+}
+
+int
+main()
+{
+ Context ctx;
+
+ bench<BenchAnd>(ctx, "and");
+ bench<BenchOr>(ctx, "or");
+ bench<BenchXor>(ctx, "xor");
+ bench<BenchNone>(ctx, "none");
+
+ bench<BenchSetOne>(ctx, "set_one");
+ bench<BenchSetAll>(ctx, "set_all");
+
+ bench<BenchResetOne>(ctx, "reset_one");
+ bench<BenchResetAll>(ctx, "reset_all");
+
+ bench<BenchFlipOne>(ctx, "flip_one");
+ bench<BenchFlipAll>(ctx, "flip_all");
+
+ bench<BenchCount>(ctx, "count");
+ bench<BenchFindFirst>(ctx, "find_first");
+
+ bench<BenchLeftShift>(ctx, "left_shift");
+ bench<BenchRightShift>(ctx, "right_shift");
+
+ bench<BenchLeftRotate>(ctx, "left_rotate");
+ bench<BenchRightRotate>(ctx, "right_rotate");
+
+ bench<BenchGrayCode>(ctx, "gray_code");
+ bench<BenchGrayCodeInv>(ctx, "gray_code_inv");
+
+ bench<BenchComparison>(ctx, "comparison");
+ bench<BenchIteration>(ctx, "iteration");
+
+ return 0;
+}