譯文:ovs+dpdk中的“vHost User NUMA感知”特性


  本文描述了“vHost User NUMA感知”的概念,該特性的測試表現,以及該特性為ovs+dpdk帶來的性能提升。本文的目標受眾是那些希望了解ovs+dpdk底層細節的人,如果你正在使用ovs+dpdk在NUMA host上配置虛擬化平台,使用vHost User類型的port作為guest的虛擬網絡配置,那么本文或許會給你一些優化性能的靈感。
 
  注意:在本文成文之際,vHost User NUMA感知這個特性僅在OVS master分支上可用。要下載OVS master分支,請戳這里。要獲取ovs+dpdk的配置步驟,請戳這里
 

vHost User NUMA感知

  vHost User NUMA感知特性在DPDK 2.2版本時引入,該特性的引入是為了解決DPDK中的一個拖后腿的地方:在多NUMA節點的環境中使用DPDK,vHost的內存分配效率比較低。為了了解這個拖后腿的點,我們先必須了解vHost User設備使用的三種內存:
  • 由DPDK分配管理的內存,Device tracking memory
  • 由OVS分配管理的內存,mbufs
  • 由QEMU管理分配的內存,Guest memory(device and memory buffers)
  在多NUMA節點環境中,顯然如果要優化性能,這三種內存應當分配在同一個NUMA節點上。但就這個小小的要求,在DPDK 2.2版本之前都是不可能達到的,因為在2.2版本之前,所有由DPDK分配管理的Device tracking memory內存,都來自同一個NUMA節點,即便使用這些內存的vHost User設備被其它NUMA節點上跑着的虛擬機使用着。這就會有一種尷尬的場景出現:一台虛擬機,QEMU為它分配的guest memory在節點A上,而DPDK的device tracking memory在另外一個節點B上。這種尷尬的場景會直接導致Intel QuickPath Interconnect(QPI)堵車,顯然也會有其它方面潛在的性能損耗。這個場景的示意圖如下:

 

 
  在DPDK 2.2版本之后,DPDK中的vHost結構被優化成了動態的與QEMU管理的guest memory貼在一起。這時,當一個vHost設備出生的時候,DPDK為它分配的內存不再固定,變得有點像一個臨時內存區,這個vHost設備將在這個臨時內存區開心的活着,直到QEMU通知DPDK:“嘿,小同志,我需要一個vHost設備”。當QEMU向DPDK索取一個vHost設備的時候,顯然QEMU需要向DPDK發送消息,而DPDK就可以利用這個消息去確定這個索要vHost設備的虛擬機位於哪個NUMA節點,之后,這個vHost設備的內存也將遷移至這個NUMA節點上。
  換句話說,vHost設備出生時居住在一個臨時住所,直至QEMU前來領養它,之后它才有一個穩定的家。
 
  現在我們解決了2/3的問題,還有一部分內存上文沒有提到,那就是由OVS分配管理的mbufs。這些內存由OVS分配管理,旨在提高datapath的運行效率,為了優化性能,顯然它們也應當與QEMU及DPDK管理分配的內存位於內一個NUMA節點上。目前,這個功能由DPDK向OVS發送消息實現,DPDK會向OVS發送有關虛擬機依存的NUMA節點信息的消息,之后OVS將把mbufs使用的內存分配在正確的NUMA節點上。在DPDK向OVS發送這些消息之前,mbufs的內存始終分配在DPDK master lcore所在的NUMA節點上。
 
  現在三部分內存都位於同一個NUMA節點了,還剩下最后一個問題:PMD輪詢線程(poll mode driver threads)。
  PMD輪詢線程是一些比較苦逼的線程,它們日夜不停馬不停蹄的輪詢input ports,對收到的包進行分類,並對包執行相應的actions。在“vHost User NUMA感知”特性出現之前,所有OVS中的PMD輪詢線程都住在同一個NUMA節點上,即是DPDK的master lcore所在的NUMA節點。終於,現在,社會解放了,好日子來了,PMD輪詢線程和mbufs、guest memory、device tracking memory呆在同一個NUMA節點了。
  下圖展示了三塊內存及PMD輪詢線程位於同一個NUMA節點時的場景:

 

 
性能測試環境
測試環境需要一個至少有兩個NUMA節點的host。上面跑着ovs+dpdk,ovs-bridge上有兩個vHost User設備,我們稱之分別為vhost0與vhost1。兩個虛擬機跑在不同的NUMA節點上,分別稱之為vm0與vm1。vhost0與vm0是一對,vhost1與vm1是一對。
下面是測試環境的規格:
Processor          E5-2695 v3
Kernel             4.2.8-200
OS                 Fedora* 22
QEMU*              2.6.0
DPDK               16.04
OVS                914403294be2
 
測試環境配置過程
  在安裝DPDK與OVS之前,確保NUMA庫已安裝
sudo yum install numactl-libs
sudo yum install numactl-devel

  確保編譯DPDK時打開了以下的配置項

CONFIG_RTE_LIBRTE_VHOST_NUMA=y

  編譯DPDK

  鏈接DPDK庫,編譯OVS
  這些都沒啥可說的,畢竟裝了幾百回了,閉着眼睛也會做了。
  配置ovs-bridge,就像上面說的那樣:創建一個ovs-bridge,在下面創建兩個ovs-port,類型為dpdkvhostuser或dpdkvhostuserclient。設置ovs的other_config:pmd-cpu-mask掩碼時,為兩個NUMA節點雨露均沾,平均分配。比如,在一個28個邏輯核心的機器上,0~13號核心在NUMA節點0上,14~17號核心在NUMA節點1上,那么如下設置就是雨露均沾:
ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=10001
# 10001是16進制,翻譯成二進制是10000000000000001,即PMD輪詢線程的核心親合設置為0號核心與16號核心兩個核心,其中0號核心位於NUMA節點0,1號核心位於NUMA節點1
# 這篇文章比較奇怪,只有一個cpu socket,這個cpu型號,即E5 2695 v3是14核心28線程的,按理來說應該只有一個numa節點啊。難道用一個cpu socket也能組兩個numa節點?

  在啟動虛擬機之前,使用如下命令檢查一個pmd設置

ovs-appctl dpif-netdev/pmd-rxq-show

  在啟動虛擬機之前,QEMU還沒有分配內存,也肯定談不上發消息給DPDK,DPDK就更談不上發消息給OVS了,所以此時這時PMD線程將落在同一個NUMA節點上,顯示如下:

pmd thread numa_id 0 core_id 0:
        port: dpdkvhostuser1    queue-id: 0
        port: dpdkvhostuser0    queue-id: 0
  然后啟動虛擬機,在兩個NUMA節點上分別啟動vm0與vm1,下面以qemu為例,為了確保兩個虛擬機分別跑在兩個NUMA節點上,使用taskset命令,如下:
sudo taskset 0x2 qemu-system-x86_64 -name vm0 -cpu ...
sudo taskset 0x2000 qemu-system-x86_64 -name vm1 -cpu ...

  這時查看虛擬機的log,vm1會打印出如下的log:

VHOST_CONFIG: read message VHOST_USER_SET_VRING_ADDR
VHOST_CONFIG: reallocate vq from 0 to 1 node
VHOST_CONFIG: reallocate dev from 0 to 1 node

  出現上面這樣的log就意味着DPDK的device tracking memory被從臨時住所挪到了正確的NUMA節點上

  另外一個驗證方法是使用pmd-rxq-show工具,顯示如下:
pmd thread numa_id 1 core_id 20:
        port: dpdkvhostuser1    queue-id: 0
pmd thread numa_id 0 core_id 0:
        port: dpdkvhostuser0    queue-id: 0
  dpdkvhostuser1現在被一個位於NUMA節點1上的線程服務着,這也正是vm1所在的NUMA節點
 
 
 
 
 
 
 
 
 
 


免責聲明!

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



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