1. 程式人生 > >程序上下文切換 – 殘酷的效能殺手(下)

程序上下文切換 – 殘酷的效能殺手(下)

幾個月一直懶得沒動筆寫寫部落格,最近開始動筆寫點什麼,今天就趁著加班出版本,橫下心決定把上次爛尾的文章給收了(上篇:https://blog.csdn.net/zhangmingcai/article/details/84823156)。

接上篇,我們已經通過分析核心程式碼看到pthread_cond_signal和pthread_cond_wait會發生CS(Context Switch),本篇我將從實際測試資料出發,來看CS究竟會對我們的應用程式產生怎樣的影響。

一般我們可以通過工具vmstat, dstat, pidstat來觀察CS的切換情況。

vmstat, dstat只能觀察整個系統的切換情況,而pidstat可以更精確地觀察某個程序的上下文切換情況。

 

這裡我用了chaos庫中task_service的一個測試用例來說明情況(chaos庫是我寫得一個高效能併發網路庫,而task_service是一個提供了多執行緒通訊的非同步訊息佇列)https://github.com/lyjdamzwf/chaos/blob/master/chaos/task_service/task_service.h

https://github.com/lyjdamzwf/chaos/blob/master/chaos/task_service/task_service.cpp

這兩個檔案中,在post非同步訊息給task_service_t時,會根據標頭檔案中定義的巨集在編譯期控制呼叫pthread_cond_signal還是write(fd),這是典型的生產者消費者模型

注意,通過系統呼叫write來通知task_service_t內部的執行緒會有以下幾種可能:

*) pipe

*) socketpair

*) eventfd

它們都是linux中的多程序/多執行緒通訊的常用手段

我們直接跑一下chaos/test/task_service 下的用例來分別看下不同機制的結果吧

  CS/s post cost exec cost
pthread_cond_wat/pthread_cond_signal 600k 32,235,597 us 32,235,078 us
sleep 300 3,987,928 us 3,996,383 us
pipe 500 11,928,024 us 11,928,174 us
socket_pair 4000 16,532,314 us 16,532,461 us
eventfd 200 5,136,712 us 5,303,645 us
boost::io_service 750k 26,355,836 us 26,355,708 us

好,讓我們一個一個來解讀

首先,使用了pthread的條件變數的chaos::task_service引起的CS非常之大,效率也是最慢,原因其實上篇已經講述,不管是pthread_cond_wait還是pthread_cond_signal,都會發生一次CS。

使用了sleep的chaos::task_service,效率是最高的,主要原因是在於生產者每次投遞時不需要系統呼叫進行notify,且CS也是很小的,但是這種模型在理論上沒有其他 wait/notify的模型要來的好,而且CS和整體的效率還和sleep的引數有關

pipe, socket_pair 和 eventfd 都是基於 write系統呼叫來notify消費者,eventfd是最新核心提供的機制,幾乎感受不到的CS讓其效率也遙遙領先其他的通訊機制

值得注意的是boost::io_service,我這裡的測試系統是linux,windows上的boost::io_service實現沒有測試,但其CS切換如此之高,卻整體效率比chaos::task_service使用pthread 條件變數的模型來得快一些,我想應該是由於其內部的佇列實現,畢竟目前chaos::task_service的佇列只是簡單的lock deque。

基於以上統計,我們可以看出基本是呈現CS越少,整體執行效率越高的趨勢

我們可以得出一個比較淺顯的結論是,CS起碼會是影響我們程式效能的主要因素之一

當然,任何時候我都覺得測試資料只是眼前的測試資料,它只能告訴我們什麼東西值得我們去注意,而不是什麼東西一定是怎樣的,至少對於後臺服務,CS應該是我們常常需要去考量效能的一個因素

好了,就到這,希望對大家有幫助

本文轉自https://www.cnblogs.com/xumaojun/p/8531951.html