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