2020-12-26 14:12:05 -08:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
2018-08-19 01:01:10 -07:00
|
|
|
|
|
|
|
|
#include "wpi/spinlock.h" // NOLINT(build/include_order)
|
|
|
|
|
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <mutex>
|
|
|
|
|
#include <thread>
|
|
|
|
|
|
2023-08-28 15:13:34 -07:00
|
|
|
#include <fmt/core.h>
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
2018-08-19 01:01:10 -07:00
|
|
|
#include "wpi/mutex.h"
|
|
|
|
|
|
|
|
|
|
static std::mutex std_mutex;
|
|
|
|
|
static std::recursive_mutex std_recursive_mutex;
|
|
|
|
|
static wpi::mutex wpi_mutex;
|
|
|
|
|
static wpi::recursive_mutex wpi_recursive_mutex;
|
|
|
|
|
static wpi::spinlock spinlock;
|
|
|
|
|
static wpi::recursive_spinlock1 recursive_spinlock1;
|
|
|
|
|
static wpi::recursive_spinlock2 recursive_spinlock2;
|
|
|
|
|
static wpi::recursive_spinlock recursive_spinlock;
|
|
|
|
|
|
|
|
|
|
TEST(SpinlockTest, Benchmark) {
|
2018-08-19 17:25:20 -07:00
|
|
|
using std::chrono::duration_cast;
|
|
|
|
|
using std::chrono::high_resolution_clock;
|
|
|
|
|
using std::chrono::microseconds;
|
2018-08-19 01:01:10 -07:00
|
|
|
|
|
|
|
|
// warmup
|
|
|
|
|
std::thread thr([]() {
|
2023-06-20 10:55:05 -07:00
|
|
|
[[maybe_unused]] int value = 0;
|
2018-08-19 01:01:10 -07:00
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 10000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(std_mutex);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
|
|
|
|
(void)start;
|
|
|
|
|
(void)stop;
|
|
|
|
|
});
|
|
|
|
|
thr.join();
|
|
|
|
|
|
|
|
|
|
std::thread thrb([]() {
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 1000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(std_mutex);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
2021-08-19 20:31:14 -07:00
|
|
|
fmt::print("std::mutex sizeof: {} time: {} value: {}\n", sizeof(std_mutex),
|
|
|
|
|
duration_cast<microseconds>(stop - start).count(), value);
|
2018-08-19 01:01:10 -07:00
|
|
|
});
|
|
|
|
|
thrb.join();
|
|
|
|
|
|
|
|
|
|
std::thread thrb2([]() {
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 1000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(std_recursive_mutex);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
2021-08-19 20:31:14 -07:00
|
|
|
fmt::print("std::recursive_mutex sizeof: {} time: {} value: {}\n",
|
|
|
|
|
sizeof(std_recursive_mutex),
|
|
|
|
|
duration_cast<microseconds>(stop - start).count(), value);
|
2018-08-19 01:01:10 -07:00
|
|
|
});
|
|
|
|
|
thrb2.join();
|
|
|
|
|
|
|
|
|
|
std::thread thr2([]() {
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 1000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(wpi_mutex);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
2021-08-19 20:31:14 -07:00
|
|
|
fmt::print("wpi::mutex sizeof: {} time: {} value: {}\n", sizeof(wpi_mutex),
|
|
|
|
|
duration_cast<microseconds>(stop - start).count(), value);
|
2018-08-19 01:01:10 -07:00
|
|
|
});
|
|
|
|
|
thr2.join();
|
|
|
|
|
|
|
|
|
|
std::thread thr2b([]() {
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 1000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(wpi_recursive_mutex);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
2021-08-19 20:31:14 -07:00
|
|
|
fmt::print("wpi::recursive_mutex sizeof: {} time: {} value: {}\n",
|
|
|
|
|
sizeof(wpi_recursive_mutex),
|
|
|
|
|
duration_cast<microseconds>(stop - start).count(), value);
|
2018-08-19 01:01:10 -07:00
|
|
|
});
|
|
|
|
|
thr2b.join();
|
|
|
|
|
|
|
|
|
|
std::thread thr3([]() {
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 1000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(spinlock);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
2021-08-19 20:31:14 -07:00
|
|
|
fmt::print("spinlock sizeof: {} time: {} value: {}\n", sizeof(spinlock),
|
|
|
|
|
duration_cast<microseconds>(stop - start).count(), value);
|
2018-08-19 01:01:10 -07:00
|
|
|
});
|
|
|
|
|
thr3.join();
|
|
|
|
|
|
|
|
|
|
std::thread thr4([]() {
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 1000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(recursive_spinlock1);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
2021-08-19 20:31:14 -07:00
|
|
|
fmt::print("recursive_spinlock1 sizeof: {} time: {} value: {}\n",
|
|
|
|
|
sizeof(recursive_spinlock1),
|
|
|
|
|
duration_cast<microseconds>(stop - start).count(), value);
|
2018-08-19 01:01:10 -07:00
|
|
|
});
|
|
|
|
|
thr4.join();
|
|
|
|
|
|
|
|
|
|
std::thread thr4b([]() {
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 1000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(recursive_spinlock2);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
2021-08-19 20:31:14 -07:00
|
|
|
fmt::print("recursive_spinlock2 sizeof: {} time: {} value: {}\n",
|
|
|
|
|
sizeof(recursive_spinlock2),
|
|
|
|
|
duration_cast<microseconds>(stop - start).count(), value);
|
2018-08-19 01:01:10 -07:00
|
|
|
});
|
|
|
|
|
thr4b.join();
|
|
|
|
|
|
|
|
|
|
std::thread thr4c([]() {
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
auto start = high_resolution_clock::now();
|
|
|
|
|
for (int i = 0; i < 1000000; i++) {
|
2019-07-08 22:58:39 -07:00
|
|
|
std::scoped_lock lock(recursive_spinlock);
|
2018-08-19 01:01:10 -07:00
|
|
|
++value;
|
|
|
|
|
}
|
|
|
|
|
auto stop = high_resolution_clock::now();
|
2021-08-19 20:31:14 -07:00
|
|
|
fmt::print("recursive_spinlock sizeof: {} time: {} value: {}\n",
|
|
|
|
|
sizeof(recursive_spinlock),
|
|
|
|
|
duration_cast<microseconds>(stop - start).count(), value);
|
2018-08-19 01:01:10 -07:00
|
|
|
});
|
|
|
|
|
thr4c.join();
|
|
|
|
|
}
|