lockfree buffer test
性能測試(3): 對無鎖隊列boost::lockfree::queue和moodycamel::ConcurrentQueue做一個性能對比測試
版權聲明:本文為博主zieckey原創文章,轉載時請保留版權信息。 https://blog.csdn.net/zieckey/article/details/69803011English version : The performance benchmark of queue with std::mutex against boost::lockfree::queue and moodycamel::ConcurrentQueue
Brief
我們使用https://github.com/Qihoo360/evpp項目中的EventLoop::QueueInLoop(...)函數來做這個性能測試。我們通過該函數能夠將一個仿函數執行體從一個線程調度到另一個線程中執行。這是一個典型的生產者和消費者問題。
我們用一個隊列來保存這種仿函數執行體。多個生產者線程向這個隊列寫入仿函數執行體,一個消費者線程從隊列中取出仿函數執行體來執行。為了保證隊列的線程安全問題,我們可以使用一個鎖來保護這個隊列,或者使用無鎖隊列機制來解決安全問題。EventLoop::QueueInLoop(...)函數通過通定義實現了三種不同模式的跨線程交換數據的隊列。
測試對象
- 帶鎖的隊列用std::vector和std::mutex來實現,具體的 gcc 版本為 4.8.2
- boost::lockfree::queue from boost-1.53
- moodycamel::ConcurrentQueue with commit c54341183f8674c575913a65ef7c651ecce47243
測試環境
測試方法
測試代碼請參考https://github.com/Qihoo360/evpp/blob/master/benchmark/post_task/post_task6.cc. 在一個消費者線程中運行一個EventLoop對象loop_,多個生產者線程不停的調用loop_->QueueInLoop(...)方法將仿函數執行體放入到消費者的隊列中讓其消費(執行)。每個生產者線程放入一定總數(由運行參數指定)的仿函數執行體之后就停下來,等消費者線程完全消費完所有的仿函數執行體之后,程序退出,并記錄開始和結束時間。
為了便于大家閱讀,現將相關代碼的核心部分摘錄如下。
event_loop.h中定義了隊列:
std::shared_ptr<PipeEventWatcher> watcher_; #ifdef H_HAVE_BOOSTboost::lockfree::queue<Functor*>* pending_functors_; #elif defined(H_HAVE_CAMERON314_CONCURRENTQUEUE) moodycamel::ConcurrentQueue<Functor>* pending_functors_; #else std::mutex mutex_; std::vector<Functor>* pending_functors_; // @Guarded By mutex_ #endif?
event_loop.cc中定義了QueueInLoop(...)的具體實現:
void Init() {watcher_->Watch(std::bind(&EventLoop::DoPendingFunctors, this)); }void EventLoop::QueueInLoop(const Functor& cb) { { #ifdef H_HAVE_BOOST auto f = new Functor(cb); while (!pending_functors_->push(f)) { } #elif defined(H_HAVE_CAMERON314_CONCURRENTQUEUE) while (!pending_functors_->enqueue(cb)) { } #else std::lock_guard<std::mutex> lock(mutex_); pending_functors_->emplace_back(cb); #endif } watcher_->Notify(); } void EventLoop::DoPendingFunctors() { #ifdef H_HAVE_BOOST Functor* f = nullptr; while (pending_functors_->pop(f)) { (*f)(); delete f; } #elif defined(H_HAVE_CAMERON314_CONCURRENTQUEUE) Functor f; while (pending_functors_->try_dequeue(f)) { f(); --pending_functor_count_; } #else std::vector<Functor> functors; { std::lock_guard<std::mutex> lock(mutex_); notified_.store(false); pending_functors_->swap(functors); } for (size_t i = 0; i < functors.size(); ++i) { functors[i](); } #endif }?
我們進行了兩種測試:
測試結論
因此,上述對比測試結論,就我們的evpp項目中的EventLoop的實現方式,我們推薦使用moodycamel::ConcurrentQueue來實現跨線程的數據交換。
更詳細的測試數據,請參考下面的兩個圖表。
縱軸是執行耗時,越低性能越高。
圖1,生產者和消費者都只有一個,橫軸是測試的批次:
圖2,生產者線程有多個,橫軸是生產者線程的個數,分別是2/4/6/8/12/16/20:
其他的性能測試報告
The IO Event performance benchmark against Boost.Asio : evpp is higher than asio about 20%~50% in this case
The ping-pong benchmark against Boost.Asio : evpp is higher than asio about 5%~20% in this case
The throughput benchmark against libevent2 : evpp is higher than libevent about 17%~130% in this case
The performance benchmark of queue with std::mutex against boost::lockfree::queue and moodycamel::ConcurrentQueue : moodycamel::ConcurrentQueue is the best, the average is higher than boost::lockfree::queue about 25%~100% and higher than queue with std::mutex about 100%~500%
The throughput benchmark against Boost.Asio : evpp and asio have the similar performance in this case
The throughput benchmark against Boost.Asio(中文) : evpp and asio have the similar performance in this case
The throughput benchmark against muduo(中文) : evpp and muduo have the similar performance in this case
最后
報告中的圖表是使用gochart繪制的。
非常感謝您的閱讀。如果您有任何疑問,請隨時在https://github.com/Qihoo360/evpp/issues跟我們討論。謝謝。
轉載于:https://www.cnblogs.com/lvdongjie/p/9681536.html
總結
以上是生活随笔為你收集整理的lockfree buffer test的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [USACO5.3]校园网Network
- 下一篇: slor6.6 在linux下的安装以及