linux 用户空间优化中断 irqbalance机制 简介
目錄
1. object tree
2. 數(shù)據(jù)結構
2.2. topo_obj
3. irqbalance處理流程
?3.1 build_object_tree
3.2 clear_work_stats
3.3 parse_proc_interrupts
3.4 parse_proc_stats
3.5 update_migration_status
3.6 calculate_placement
3.7 activate_mapping
4. powersave mode
5. 補充
本文檔基于irqbalance-1.5.0
源碼鏈接:https://launchpad.net/ubuntu/+source/irqbalance/
1. object tree
?????? Irqbalance是用戶空間用于優(yōu)化中斷的一個工具,通過周期性的(默認10s)統(tǒng)計各個cpu上的中斷情況,重新對中斷進行再分配,實現(xiàn)各個cpu上中斷負載相對均衡。中斷均衡是建立再“object tree”的基礎之上的,object?? tree則是通過系統(tǒng)的拓撲結構建立的分層結構。根據(jù)系統(tǒng)結構屬性NUMA node/packet/cache affinity可以將系統(tǒng)劃分為自上而下的四層:node->package->cache->cpu。
?????? 以16核雙路服務器為例,系統(tǒng)有兩個numa node,每個節(jié)點包含兩個cluster,每個cluster包含4個cores,共享l2 cache。其結構簡圖如下:
????????????????????? ? ? ? ? ? ? ? ? ? ?? ??
對應的object tree拓撲結構如圖:
?
其中:
(1)每個節(jié)點為一個object,通過struct topo_obj描述。
(2)上下層之間的節(jié)點通過parent/child指針管理
(3)每一層都有一個全局鏈表頭指針,用于組織管理處于同一層的所有節(jié)點。
?
2. 數(shù)據(jù)結構
2.1 Irq_info
?????? 在樹形拓撲結構建立之后,就需要統(tǒng)計各個節(jié)點上中斷負載的信息,以便為重新分配中斷提供依據(jù)。對于各個中斷信息通過struct irq_info來描述。下面結合各個字段介紹下irqlabalance中幾個比較關鍵的概念。
struct irq_info {int irq; //中斷號int class;int type;int level;int flags;struct topo_obj *numa_node; //中斷當前所在node節(jié)點對應的objectcpumask_t cpumask;uint64_t irq_count;uint64_t last_irq_count;uint64_t load;int moved;struct topo_obj *assigned_obj; //中斷被分配到節(jié)點對應的objectchar *name; };(1) 中斷類型(irq_info.class)
Irqbalance根據(jù)中斷所屬device的pci配置空間class code把中斷分成了以下8種類型字。
#define IRQ_OTHER 0 #define IRQ_LEGACY 1 #define IRQ_SCSI 2 #define IRQ_TIMER 3 #define IRQ_ETH 4 #define IRQ_GBETH 5 #define IRQ_10GBETH 6 #define IRQ_VIRT_EVENT 7其中:irq_info.class 與 pci配置空間 class code的映射關系如下:
?
?
(2) 中斷層級(irq_info.level)
每種中斷類型根據(jù)靜態(tài)映射分別對應一種分配方式,分配方式一共有4種。
#define BALANCE_NONE 0 //表示中斷不能進行遷移 #define BALANCE_PACKAGE 1 //表示中斷只能在package層進行均衡 #define BALANCE_CACHE 2 //表示中斷只能在cache層進行均衡 #define BALANCE_CORE 3 //表示中斷只能在core層進行均衡中斷類型與其映射關系如表:
?
(3) 中斷計數(shù)
?????? irq_info.irq_count 表示本次統(tǒng)計irq中斷在各個cpu上產(chǎn)生的中斷次數(shù)之和。
?????? irq_info.last_irq_count表示上次統(tǒng)計irq中斷在各個cpu上的產(chǎn)生的中斷次數(shù)之和。
?
(4) 中斷的負載
?????? 表示兩次統(tǒng)計這段時間內(nèi)中斷增加所帶來的負擔。在irqbalance中把中斷消耗的時間來衡量cpu的負擔。
計算方法詳見3.4(4).
2.2. topo_obj
“對象樹“中的每個節(jié)點均為一個對象,通過struct topo_obj進行描述。
struct topo_obj {uint64_t load;uint64_t last_load;uint64_t irq_count;enum obj_type_e obj_type; //區(qū)別該節(jié)點位于哪一層。int number; // object對應的索引int powersave_mode;cpumask_t mask; //該節(jié)點下包含哪幾個cpuGList *interrupts; //組織被分配到該obj的中斷struct topo_obj *parent; //指向其上一層父對象的objGList *children; //組織管理該obj包含的下層objGList *numa_nodes; //指向最頂層所在node節(jié)點的objGList **obj_type_list; };(1) object節(jié)點的負載(topo_obj.load)
- cpu節(jié)點的load計算方法:
在/proc/stat獲取每個cpu的信息如下:
其中第6/7項,分別代表自系統(tǒng)啟動以來硬/軟中斷累計時間(單位是jiffies)。
cpu負載:單個周期(10s)內(nèi),cpu處理軟、硬中斷的時間之和。
- cpu拓撲層以上層各個節(jié)點的負載:
父節(jié)點負載等于各孩子節(jié)點負載的總和 。
(2) 節(jié)點中斷管理指針(topo_obj.interrupts)
?????? 所有被分配到該節(jié)點上的中斷都掛在該指針上。
(3) 節(jié)點中斷計數(shù)(topo_obj.irq_count)
分配到該節(jié)點上的所有中斷(即interrupts指針管理的鏈表上的中斷)在單位周期(10s)內(nèi)增加的次數(shù)之和。
(4) 節(jié)點的object類型(topo_obj.obj_type)
?????? object的類型,用來表明該對象處在對象樹的哪一層次。Irqbalance 定義了如下4種類型。
OBJ_TYPE_CPU,OBJ_TYPE_CACHE,OBJ_TYPE_PACKAGE,OBJ_TYPE_NODE(5) powersave_mode
?????? 用來表示該object是否處在省電模式。具體介紹詳見4。
?????? Irqbalance默認是關閉powersave_mode的,但是用戶可以通過irqbalance -p <n>來設置power_thresh。當系統(tǒng)內(nèi)object的負載較小時,會自動切換到省電模式。
3. irqbalance處理流程
Irqbalance會周期性的(10s)統(tǒng)計系統(tǒng)中斷的情況,主要的處理流程圖如下:
?
?
下面針對各個部分作具體介紹:
?3.1 build_object_tree
(1)作用:
主要實現(xiàn)建立拓撲結構各個節(jié)點以及中斷數(shù)據(jù)結構,并初始化。
(2)實現(xiàn):
?????? 通過遍歷/sys/devices/system/node/node[*],決定有多少OBJ_TYPE_NODE的對象。
通過遍歷/sys/devices/system/cpu/cpu[*],以及是否online,決定有多少OBJ_TYPE_CPU的對象
通過遍歷/sys/devices/system/cpu/cpu[*]/cache/index[MAX]/shared_cpu_map決定有多少OBJ_TYPE_CACHE對象。
通過遍歷/topology/physical_package_id決定有多少OBJ_TYPE_PACKAGE的對象。
通過遍歷/sys/bus/pci/devices/0000:00:[**].[*]/下irq以及msi,建立各個irq的數(shù)據(jù),并結合proc/irq/下文件初始化中斷數(shù)據(jù)結構。這樣irqbalance就知道該irq屬于哪個node以及smp_affinity.
3.2 clear_work_stats
清除各個對象節(jié)點上分配中的負載值,以便重新賦值。
3.3 parse_proc_interrupts
?????? 通過分析/proc/interrupts文件,更新各個irq在所有cpu上中斷次數(shù)的累加和。
3.4 parse_proc_stats
(1) 計算各個對象節(jié)點的load,并更新到topo_obj.load。
cpu節(jié)點的負載: 通過分析/proc/stats統(tǒng)計硬/軟中斷的累計時間。
其余節(jié)點的負載:父節(jié)點負載=各孩子節(jié)點負載的總和
(2) 計算各個對象節(jié)點上所有中斷在單位周期(10s) 內(nèi)新增加的次數(shù),并更新到load_slice.irq_count。
(3) 計算各個對象節(jié)點上單位周期內(nèi)平均中斷數(shù)local_count。
?????? 由于分配到上層節(jié)點的中斷最終要“均分”給下層,所以obj平均中斷數(shù)loacl_count=obj.irq_cpunt +parent_obj.irq_count/(parent_obj的子節(jié)點數(shù))。如圖所示:
?
?
?(4) 計算對象上各個中斷負載 irq_info.load
?????? 單次中斷對obj節(jié)點的負載貢獻值(load_slice),即節(jié)點負載除以平均中斷數(shù):
?????? load_slice = topo_obj.load/local_count.
?????? 那么該對象節(jié)點上各個中斷負載就等于單次中斷負載貢獻值與中斷次數(shù)的乘積:
irq_info.load= load_slice*(irq_info.irq_count- irq_info.last_irq_count)
3.5 update_migration_status
通過平衡算法找出需要重新分配的中斷。自下而上遍歷各個拓撲層,針對每一層:
(1)遍歷該層各個對象節(jié)點,計算該層的平均負載avg_load、標準方差std_deviation以及節(jié)點中負載最小值min_load.
(2)再次遍歷該層各個拓撲節(jié)點,找到大于min-_load的節(jié)點,然后把該節(jié)點中的中斷按照中斷的irq_info.class由大到小并負載情況由大到小進行排序,然后依次從該節(jié)點移除,放到表頭為rebalance_irq_list的鏈表中。
注意:中斷從節(jié)點遷移后會更新該節(jié)點的負載以及min_load,當兩者最接近時停止遷移中斷。
? 也就是說該步驟過后,需要遷移的中斷都被放在了表頭為rebalance_irq_list的鏈表中,后續(xù)會將這些中斷重新分配。
3.6 calculate_placement
(1) 將存在rebalance_irq_list鏈表中的中斷重新排序:優(yōu)先按照中斷的irq_info.class由大到小排列,如果class相同則按照load由大到小排列。
(2) 首先根據(jù)中斷所在的numa nodeid將中斷分配到不同的node 節(jié)點上。從這里可以看出中斷是不會跨numa 節(jié)點遷移的,只能在同一numa node內(nèi)部進行優(yōu)化。
(3) 自上而下遍歷各個個拓撲層,對于每一拓撲層:
遍歷該層節(jié)點上的中斷,對每一個中斷:
遍歷該節(jié)點所有孩子節(jié)點,將其遷移到負載最小的孩子節(jié)點上。
3.7 activate_mapping
?????? 通過修改/proc/irq/[*]/smp_affinity,使處理生效
4. powersave mode
Irqbalance支持powersave mode,默認是關閉的,但是用戶可以通過irqbalance -p <n>來設置閾值power_thresh。開啟該mode,Irqbalance會根據(jù)系統(tǒng)內(nèi)object的負載情況,會自動將某個cpu object切換省電模式/正常模式。
前面3.5小節(jié)(1)中,當遍歷cpu層各個對象節(jié)點,根據(jù)load值計算出cpu平均負載avg_load、標準方差std_deviation后。
?????? (1) 如果load + std_deviation <= avg_load時,表明該cpu的負載較低,則會記錄該cpu object,同時記錄低負載的cpu個數(shù)
?????? (2)如果load - std_deviation >= avg_load時,表明該cpu 的負載比較高,也會記錄高負載的cpu個數(shù)。
?
在遍歷完整個cpu層的所有節(jié)點后,如果不存在高負載cpu,同時低負載的cpu個數(shù)大于設定閾值,則會將最后記錄的cpu對象的powersaved_mode字段置1. 后續(xù)在從rebalance_irq_list的鏈表重新分配中斷時,就不會在分配到該cpu上。
一旦系統(tǒng)中存在高負載cpu,irqlabalance就會清除所有cpu 對象的powersaved_mode,恢復正常模式。
5. 補充
1. 中斷再分配時,需要先自上而下遍歷各層各節(jié)點,將符合條件的節(jié)點上的中斷先遷移到表頭為rebalance_irq_list的鏈表中,然后再將鏈表中的中斷按node->package->cache->cpu逐層分配到各個節(jié)點中(分配時會根據(jù)irq_info.level決定最終分配到哪一級節(jié)點上)。那么剛建立號中斷數(shù)據(jù)庫時,各個節(jié)點上還沒有中斷那么是如何操作的呢?
?????? 剛建的中斷數(shù)據(jù)庫由指真interrupts_db來管理,初次建立好后會將所有的中斷遷移到rebalance_irq_list中。然后將rebalance_irq_list鏈表中中斷按node->package->cache->cpu逐層分配到各個節(jié)點中。
2. 如果一個package中有兩個node時,irqbalance的拓撲層是如何劃分的?
在這種情況下,cache domian的父節(jié)點是package,但是numa節(jié)點的子節(jié)點是cache domians,而不再是packages,同時package的子節(jié)點任然是是cache domians。如圖所示:
?
?
總結
以上是生活随笔為你收集整理的linux 用户空间优化中断 irqbalance机制 简介的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 负载均衡(Loadbalance)
- 下一篇: linux环境用xor实现加密解密,PH