说明
所用无锁队列为SPSCQueue及boost的spsc_queue。
有锁队列为PolyM,以及自己实现的有所队列,代码如下:
safequeue.cpp
#include <mutex>
#include <queue>
// Thread safe implementation of a Queue using an std::queue
template <typename T>
class SafeQueue {
private:
std::queue<T> m_queue;
std::mutex m_mutex;
public:
SafeQueue() {
}
bool empty() {
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.empty();
}
int size() {
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.size();
}
void enqueue(T& t) {
std::unique_lock<std::mutex> lock(m_mutex);
m_queue.push(t);
}
bool dequeue(T& t) {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_queue.empty()) {
return false;
}
t = std::move(m_queue.front());
m_queue.pop();
return true;
}
};
测试方法
使用SPSCQueue中的Benchmark方法,加入自己的lock queue。 有锁队列的实现如下:
std::cout << "lock Queue:" << std::endl;
{
SafeQueue<int> q;
auto t = std::thread([&] {
pinThread(cpu1);
int result;
for (int i = 0; i < iters; ++i) {
while (!q.dequeue(result))
;
if (result != i) {
throw std::runtime_error("");
}
//q.pop();
}
});
pinThread(cpu2);
auto start = std::chrono::steady_clock::now();
for (int i = 0; i < iters; ++i) {
q.enqueue(i);
}
t.join();
auto stop = std::chrono::steady_clock::now();
std::cout << iters * 1000000 /
std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count()
<< " ops/ms" << std::endl;
}
结果
cpu | SPSCQueue | LockQueue | Boost | PolyM |
---|---|---|---|---|
11th Gen Intel® Core™ i7-1165G7 @ 2.80GHz | 22607 ops/ms | 4027 ops/ms | 11650 ops/ms | 1579 ops/mn |
11th Gen Intel® Core™ i9-11980HK @ 2.60GHz | 20644 ops/ms | 3904 ops/ms | - | - |