上下文切換,你確定了解嗎?


本文由雲+社區發表

作者:cocoding

前言

聽到上下文切換,大家第一反應肯定是:一定要減少這貨出現的次數。確實上下文切換對性能的影響顯而易見,但有時又無法完全避免,這就要求我們對上下文性能損耗了然於胸,才能更准確地評估系統性能。另外,現在雲廠商提供的機器種類如此之多,虛擬機在這方面是否有區別。以上都需要有科學的方法來衡量上下文的耗時,進而幫助系統評估以及機型選擇。

本文將從這以下兩個方面來展開

  1. 上下文切換有哪些類型以及可能出現的場景
  2. 衡量各場景上下文切換耗時

1, 上下文切換類型及場景

上下文大體上可以分為兩類

  1. 進程上下文
  2. 中斷上下文

進程上下文具體包括:

(1)用戶級上下文: 正文、數據、用戶堆棧以及共享存儲區;

(2)寄存器上下文: 通用寄存器、程序寄存器(IP)、處理器狀態寄存器(EFLAGS)、棧指針(ESP);

(3)系統級上下文: 進程控制塊task_struct、內存管理信息(mm_struct、vm_area_struct、pgd、pte)、內核棧。

中斷上下文具體包括:

(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),需要進一步確認。

img1.png

因此,我們在代碼里面也要盡量減少系統調用,常見的優化方法有:每次讀寫磁盤時,使用buffer減少read/write調用次數等。

2,上下文切換性能評估

測試上下文切換性能的工具有

  1. unixbench
  2. tsuna/contextswitch

兩個工具的原理類似,都是創建兩個進程,然后互相喚醒:

(1) unixbench是創建兩個進程,兩個進程之間創建兩個管道(pipe),通過管道來互相讀寫數據,結果是10s內完成的切換次數。

(2) contextswitch同樣是創建兩個進程,通過futex(快速用戶區互斥)來互相喚醒,結果是循環500000次的耗時

進程之間的上下文切換

使用這兩個工具在測試進程上下文時,需要注意一點:把兩個進程綁定到同一個核上運行,否則可能測試的就不僅僅是進程上下文切換了,下面會介紹不綁核的情況。

unixbench

taskset -c 1 ./Run -c 1 context1

對於contextswitch

taskset -c 1 ./timectxsw

或者直接運行make或者./cpubench.sh

img2.png

從上圖可以看到,一次ctx的耗時在1012~1263ns ,但其實perf看,綁核情況下,運行timectxsw實際的ctx是在300w次(這里一次循環需要6次ctx),所以實際的ctx應該是674~842ns

img3.png

進程和中斷上下文切換

上文提到如果要測試進程上下文切換耗時就一定要綁核,否則測試的很可能會包含進程和中斷上下文切換的耗時,因為默認內核會把測試程序產生的進程調度到不同的核上,進程之間的喚醒,需要先發送IPI中斷,對方CPU在收到IPI中斷之后,會完成一次中斷上下文切換,執行中斷函數,進而再喚醒相應進程。所以在不綁核的情況下,測試的就包含了進程-中斷上下文以及中斷處理函數的耗時。

img4.png

unixbench

如果使用unixbench在騰訊雲上,默認調度到1個核上,這樣就測試的進程上下文切換,所以需要手動修改代碼綁核,或者用git上的unixbench-fix,強制將兩個進程放到不同的核上

img5.png

contextswitch

contextswitch這里還增加了在同一個NUMA上的測試,從測試數據看,兩個進程如果調度到同一個NUMA上時,耗時會更短。

img6.png

從測試數據看:

  1. 如果兩個進程跨NUMA,一次上下文切換的耗時在2500ns
  2. 如果兩個進程在同NUMA,一次上下文切換的耗時在1500ns

在虛擬機里面,跨核的上下文切換會更大,因為vcpu無法處理IPI中斷,需要退出的宿主機上處理,從而增加了上下文切換的耗時,總體上虛擬機跨核ctx的耗時是宿主機的2~3倍。

下一篇文章我們會對IPI中斷的測試方法以及虛擬化之后可能的優化方法進行介紹,歡迎訂閱,及時查看。

img

此文已由騰訊雲+社區在各渠道發布

獲取更多新鮮技術干貨,可以關注我們騰訊雲技術社區-雲加社區官方號及知乎機構號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM