Skip to content

Instantly share code, notes, and snippets.

@imos
Created October 10, 2016 19:32
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save imos/bc3e43a02ffa36a532b50fc02e4580f9 to your computer and use it in GitHub Desktop.
Save imos/bc3e43a02ffa36a532b50fc02e4580f9 to your computer and use it in GitHub Desktop.
Benchmark for std::mutex
#include <math.h>
#include <stdint.h>
#include <sys/time.h>
#include <atomic>
#include <functional>
#include <map>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
using namespace std;
typedef int64_t int64;
const double kBenchmarkDuration = 0.7;
const int kShortWait = 1000;
class BenchmarkState {
public:
BenchmarkState(const string& name) : name_(name) {}
bool KeepRunning();
private:
void PrintStats();
static double GetTime();
string name_;
double start_time_;
int64 iteration_ = 0;
int64 iteration_to_check_ = 1;
vector<pair<int64, double>> results_;
};
bool BenchmarkState::KeepRunning() {
iteration_++;
if (iteration_to_check_ == iteration_) {
if (iteration_to_check_ == 1) {
iteration_to_check_ = 2;
start_time_ = GetTime();
results_.reserve(100);
results_.emplace_back(iteration_, start_time_);
return true;
}
double current_time = GetTime();
if (current_time - start_time_ < 0.1 &&
current_time - start_time_ < kBenchmarkDuration) {
if (current_time - start_time_ < 0.01) {
iteration_to_check_ = iteration_ * 8;
} else {
iteration_to_check_ = iteration_ * 2;
}
} else {
results_.emplace_back(iteration_, current_time);
iteration_to_check_ =
iteration_ + round(iteration_ / (current_time - start_time_) / 10);
if (iteration_to_check_ <= iteration_) {
iteration_to_check_ = iteration_ + 1;
}
if (current_time - start_time_ > kBenchmarkDuration) {
PrintStats();
return false;
}
}
}
return true;
}
void BenchmarkState::PrintStats() {
double best_qps = 0;
for (int i = 1; i < results_.size(); i++) {
best_qps = max(best_qps, (results_[i].first - results_[i - 1].first) /
(results_[i].second - results_[i - 1].second));
}
printf("%32s: % 16.2f ns\n", name_.c_str(), 1e9 / best_qps);
}
double BenchmarkState::GetTime() {
struct timeval tv;
gettimeofday(&tv, nullptr);
return tv.tv_sec + tv.tv_usec * 1e-6;
}
void Benchmark(const string& name, std::function<void()> target) {
BenchmarkState state(name);
while (state.KeepRunning()) {
target();
}
}
void ShortSleep() {
for (volatile int x = 0; x < kShortWait; x++);
}
int main() {
std::atomic<bool> b;
Benchmark("Atomic", [&]() {
b = true;
b = false;
});
std::mutex m;
Benchmark("LockAndUnlock", [&]() {
m.lock();
m.unlock();
});
Benchmark("ShortSleep", [&]() {
ShortSleep();
});
m.lock();
std::atomic<bool> finished(false);
std::atomic<bool> waiting(false);
std::thread t([&]() {
while (!finished) {
while (waiting == false);
ShortSleep();
m.unlock();
m.lock();
}
});
Benchmark("LockAndUnlockWithContention", [&]() {
waiting = true;
m.lock();
waiting = false;
ShortSleep();
m.unlock();
});
waiting = true;
finished = true;
t.join();
m.unlock();
Benchmark("LockAndUnlockWithPenalty", [&]() {
waiting = true;
m.lock();
ShortSleep();
waiting = false;
ShortSleep();
m.unlock();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment