Replace expensive inverval_set intersection_of and operator==
calls with a single subset_of call. I borrowed this idea from
Piotr Dałek's "osd/PGPool: don't use intermediate interval set"
patch. The following benchmark program demonstrates a 38%
performance increase:
#include <iostream>
#include <chrono>
#include "include/interval_set.h"
#define NANOSECONDS(d) \
std::chrono::duration_cast<std::chrono::nanoseconds>(d).count()
typedef uint64_t snapid_t;
typedef std::chrono::steady_clock::duration duration;
duration PGPool_update_old(const interval_set<snapid_t> &rs) {
std::chrono::steady_clock::time_point start, end;
interval_set<snapid_t> newly_removed_snaps, cached_removed_snaps;
// initialize state
cached_removed_snaps = rs;
// start timed simulation
start = std::chrono::steady_clock::now();
{
newly_removed_snaps = cached_removed_snaps;
interval_set<snapid_t> intersection;
intersection.intersection_of(newly_removed_snaps, cached_removed_snaps);
assert(intersection == cached_removed_snaps);
cached_removed_snaps.swap(newly_removed_snaps);
newly_removed_snaps = cached_removed_snaps;
newly_removed_snaps.subtract(intersection);
}
// end timed simulation
end = std::chrono::steady_clock::now();
return end - start;
}
duration PGPool_update_new(const interval_set<snapid_t> &rs) {
std::chrono::steady_clock::time_point start, end;
interval_set<snapid_t> newly_removed_snaps, cached_removed_snaps;
// initialize state
cached_removed_snaps = rs;
// start timed simulation
start = std::chrono::steady_clock::now();
{
newly_removed_snaps = cached_removed_snaps;
assert(cached_removed_snaps.subset_of(newly_removed_snaps));
interval_set<snapid_t> removed_snaps = newly_removed_snaps;
newly_removed_snaps.subtract(cached_removed_snaps);
cached_removed_snaps.swap(removed_snaps);
}
// end timed simulation
end = std::chrono::steady_clock::now();
return end - start;
}
int main(int argc, char *argv[])
{
assert(argc == 3);
const int sample_count = std::stoi(argv[1]);
const int interval_count = std::stoi(argv[2]);
const int interval_distance = 4;
const int interval_size = 2;
const int max_offset = interval_count * interval_distance;
interval_set<snapid_t> removed_snaps;
for (int i = 0; i < max_offset; i += interval_distance)
removed_snaps.insert(i, interval_size);
duration old_delta(0), new_delta(0);
for (int i = 0; i < sample_count; ++i) {
old_delta += PGPool_update_old(removed_snaps);
new_delta += PGPool_update_new(removed_snaps);
}
float ratio = float(NANOSECONDS(old_delta)) / NANOSECONDS(new_delta);
std::cout << ratio << std::endl;
}
Suggested-by: Piotr Dałek <piotr.dalek@corp.ovh.com>
Signed-off-by: Zac Medico <zmedico@gmail.com>