本文由雲+社區發表git
做者:cocodinggithub
聽到上下文切換,你們第一反應確定是:必定要減小這貨出現的次數。確實上下文切換對性能的影響顯而易見,但有時又沒法徹底避免,這就要求咱們對上下文性能損耗瞭然於胸,才能更準確地評估系統性能。另外,如今雲廠商提供的機器種類如此之多,虛擬機在這方面是否有區別。以上都須要有科學的方法來衡量上下文的耗時,進而幫助系統評估以及機型選擇。函數
本文將從這如下兩個方面來展開工具
上下文大致上能夠分爲兩類性能
進程上下文具體包括:測試
(1)用戶級上下文: 正文、數據、用戶堆棧以及共享存儲區;優化
(2)寄存器上下文: 通用寄存器、程序寄存器(IP)、處理器狀態寄存器(EFLAGS)、棧指針(ESP);spa
(3)系統級上下文: 進程控制塊task_struct、內存管理信息(mm_struct、vm_area_struct、pgd、pte)、內核棧。3d
中斷上下文具體包括:unix
(1)硬件傳遞過來的參數
所以上下文切換能夠分爲如下幾類:
(1)進程之間的上下文切換:A進程切換到B進程
(2)進程和中斷之間的上下文切換:進程A被中斷打斷
(3)中斷之間的上下文切換:低級別中斷被高級別中斷打斷
其中第一種上下文切換最爲常見,第二種次之,第三種最少見,所以本文接下來主要討論前面兩種上下文切換的耗時。
這是要說一種特殊的上下文切換:模式切換,即進程A從用戶態由於系統調用進入內核態,這種切換之因此特殊,是由於它並無通過完整的上下文切換,只是寄存器上下文進行了切換,因此模式切換的耗時相對完整進程上下文更低。
雖然模式切換較完整上下文切換耗少,但仍不能小覷,在物理機上,一次系統調用(以SYS_gettid爲例)在50~60ns。(本文全部數據均是Intel(R) Xeon(R) V4和V5 CPU上獲得)而在虛擬機上,一次系統調用更是可能達到
240ns ,從perf來看,system_call_after_swapgs函數消耗CPU較物理機多不少,網上有人說多是爲了解決Spectre漏洞,在每次系統調 用返回用戶空間時,會清理一次BTB(branch target buffer),須要進一步確認。
1.png所以,咱們在代碼裏面也要儘可能減小系統調用,常見的優化方法有:每次讀寫磁盤時,使用buffer減小read/write調用次數等。
測試上下文切換性能的工具備
兩個工具的原理相似,都是建立兩個進程,而後互相喚醒:
(1) unixbench是建立兩個進程,兩個進程之間建立兩個管道(pipe),經過管道來互相讀寫數據,結果是10s內完成的切換次數。
(2) contextswitch一樣是建立兩個進程,經過futex(快速用戶區互斥)來互相喚醒,結果是循環500000次的耗時
使用這兩個工具在測試進程上下文時,須要注意一點:把兩個進程綁定到同一個核上運行,不然可能測試的就不只僅是進程上下文切換了,下面會介紹不綁核的狀況。
unixbench
taskset -c 1 ./Run -c 1 context1
複製代碼
對於contextswitch
taskset -c 1 ./timectxsw
複製代碼
或者直接運行make或者./cpubench.sh
2.png從上圖能夠看到,一次ctx的耗時在1012~1263ns ,但其實perf看,綁核狀況下,運行timectxsw實際的ctx是在300w次(這裏一次循環須要6次ctx),因此實際的ctx應該是674~842ns
3.png上文提到若是要測試進程上下文切換耗時就必定要綁核,不然測試的極可能會包含進程和中斷上下文切換的耗時,由於默認內核會把測試程序產生的進程調度到不一樣的核上,進程之間的喚醒,須要先發送IPI中斷,對方CPU在收到IPI中斷以後,會完成一次中斷上下文切換,執行中斷函數,進而再喚醒相應進程。因此在不綁核的狀況下,測試的就包含了進程-中斷上下文以及中斷處理函數的耗時。
4.pngunixbench
若是使用unixbench在騰訊雲上,默認調度到1個核上,這樣就測試的進程上下文切換,因此須要手動修改代碼綁核,或者用git上的unixbench-fix,強制將兩個進程放到不一樣的核上
5.pngcontextswitch
contextswitch這裏還增長了在同一個NUMA上的測試,從測試數據看,兩個進程若是調度到同一個NUMA上時,耗時會更短。
6.png從測試數據看:
在虛擬機裏面,跨核的上下文切換會更大,由於vcpu沒法處理IPI中斷,須要退出的宿主機上處理,從而增長了上下文切換的耗時,整體上虛擬機跨核ctx的耗時是宿主機的2~3倍。
此文已由騰訊雲+社區在各渠道發佈
獲取更多新鮮技術乾貨,能夠關注咱們騰訊雲技術社區-雲加社區官方號及知乎機構號