当前位置: 首页 > Linux

irqbalance详解(上)

时间:2023-04-06 05:26:37 Linux

irqbalance是什么?该项目主页有以下描述:Irqbalance是一个守护进程,用于帮助平衡由中断产生的cpu负载跨所有系统cpu。避免了单个cpu负载过载的情况发生。用法如下:root@a7661ef9b2f8test]#irqbalance-hirqbalance:optionrequiresanargument--'h'irqbalance[--oneshot|-o][--调试|-d][--前景|-f][--提示策略=|-h[精确|子集|忽略]][--banscript=|-b<脚本>][--powerthresh=|-p<关闭>|][--banirq=|-i][--policyscript=|-l<脚本>][--pid=|-s<文件>][--deepestcache=|-c]#查看当前运行状态serviceirqbalancestatus#终止服务Serviceirqbalancestop首先有一些前置知识需要讲解,涉及到irqbalancecputree的分层。Pre-knowledgeinterrupt每一个硬件设备都需要和CPU有某种形式的通信,这样CPU才能及时知道发生了什么,这样CPU才能放下手头的事情来处理紧急事件。硬件设备主动干扰CPU的现象可以称为硬件中断。就像我们正在一心一意写代码的时候,突然钉钉发出“咚咚”的声音,这时候我们就知道有事情需要处理了,这里的“咚咚”声音可以理解为中断。在CPU与硬件的通信方式中,还有一种方式叫做轮询,就是让CPU定时查询硬件状态,然后进行相应的处理。这是对CPU的浪费,属于被动硬件方式。相比之下,硬件主动方式(中断)更为有效。然后每个硬件设备都有中断。这很简单。为它们分配一个唯一的编号,即irq编号。您可以在/proc/interrupts文件的第一列中看到所有的irq。这种只支持内核2.4及以后版本将不同的硬件中断请求(IRQ)分配给特定CPU的绑定技术称为SMPIRQAffinity,后面会详细介绍。NUMA架构简单介绍一下NUMA架构。在NUMA架构出现之前,CPU频率一路越来越高,直到触及物理极限的天花板,然后转向越来越多核心的方向。如果每个core的工作性质都是share-nothing(类似于map-reduce的node节点的job属性),那么可能就没有NUMA了。由于所有CPUCores都是通过共享一个北桥读取内存,随着核心数量的发展,北桥在响应时间上的性能瓶颈越来越明显。因此,智能硬件设计者首先将内存控制器(北桥中读取内存的部分)进行拆分,分到各个die中。于是NUMA出现了!在NUMA架构中,内存访问可以分为距离和距离。只有当CPU访问直连内存对应的物理地址时,才会有较短的响应时间(LocalAccess)。而如果需要访问其他CPU附加的内存数据,则需要通过互连通道访问,响应时间会比以前慢(RemoteAccess),因此得名NUMA(Non-UniformMemoryAccess)).---引用自http://cenalulu.github.io/lin...图片看起来是这样的:numactl--hardware命令可以查看机器的numa拓扑,比如本机:[root@d2b9eb755bb1~]#numactl--hardwareavailable:2nodes(0-1)node0cpus:01234567891011242526272829303132333435node0size:130946MBnode0free:9892MBnode1cpus:121314151617181920212223363738394041424344454647node1大小:131072MBnode1免费:35969MB1010距离:0:21:10或使用此脚本[root@d2b9eb755bb1~]#foriin`ls/sys/devices/system/node|grepnode`;doecho-ne"$i\t";cat/sys/devices/system/node/$i/cpulist;donenode00-11,24-35node112-23,36-47或使用lscpu命令,[root@d2b9eb755bb1~]#lscpuArchitecture:x86_64CPUop-mode(s):32-bit,64-bitByteOrder:LittleEndianCPU(s):48On-lineCPU(s)list:0-47Thread(s)percore:每个插槽2个核心:12个插槽:2NUMA节点:2供应商ID:GenuineIntelCPU系列:6型号:79步进:1CPUMHz:2197.264BogoMIPS:4401.60虚拟化:VT-xL1d缓存:32KL1i缓存:32KL2缓存:256KL3缓存:30720KNUMAnode0CPU(s):0-11NUs(MA)12-23,36-47CPU-relatedcpucache结构图如下:从硬件上看,上图中的L1和L2Cache是??两个HT共享的,在同一个物理Core中,而L3Cache在物理CPU中.核心分享。从OS内核的角度来看,每个HT都是一个逻辑CPU。以cpu0为例,如下:[root@d2b9eb755bb1~]#tree-L1/sys/devices/system/cpu/cpu0/cache//sys/devices/system/cpu/cpu0/cache/├──index0->L1datacache├──index1->L1Instructioncache├──index2->L2cache└──index3->L3cache至此,想了解的可以翻翻以前的教材。更多的cpu信息可以从/proc/cpuinfo文件中获取。irqkinshipbinding下面结合实践简单说一下这件事。每个cpu上的中断可以在/proc/interrupts文件中看到。/proc/irq/#/smp_affinity_list可以查看当前绑定到指定中断的CPU,当然也可以看到smp_affinity这个文件,它是一个用逗号分隔的十六进制位掩码,比如0000,00000020表示这个irq是分配给CPU5。因此,使用如下脚本获取当前各网卡中断cpu的总体情况(通常只对网卡中断感兴趣):cat/proc/interrupts|grepeth0-|剪切-d:-f1|读我时;做echo-neirq":$i\tbind_cpu:";cat/proc/irq/$i/smp_affinity_list;完成|sort-n-t''-k3效果大概是这样的:irq:113bind_cpu:0irq:117bind_cpu:1irq:136bind_cpu:2irq:109bind_cpu:3irq:137bind_cpu:4irq:106bind_cpu:5irq:112bind_cpu:6irq:111bind_cpu:7irq:115bind_cpu:8irq:149bind_cpu:8irq:152bind:cpu13bind_cpu:8irq:110bind_cpu:10irq:114bind_cpu:11irq:130bind_cpu:24irq:148bind_cpu:24irq:132bind_cpu139bind_cpu:26irq:118bind_cpu:27irq:132bind_cpu:27irq:123bind_cpu:28irq:128bind_cpu:28irq:134bind_cpu:28irq:142bind_cpu:28irq:150bind_cpu:28irq:135bind_qir_cpu:28irq:135bind_qir:1:830bindqir_cpu:139116bind_cpu:31irq:119bind_cpu:32irq:124bind_cpu:32irq:126绑定cpu:32irq:138bind_cpu:32irq:151bind_cpu:32irq:107bind_cpu:33irq:121bind_cpu:34irq:140bind_cpu:34irq:120bind_cpu:35irq:122bind_cpu:35irq:125bind_cpu:125irq:125bind_cpu:125irq:125bind_c35irq:143bind_cpu:35irq:144bind_cpu:35irq:145bind_cpu:35irq:146bind_cpu:35irq:147bind_cpu:35irq:153bind_cpu:35可以看到,我的机器有一半的cpu是空闲的,已经绑定了绑定到给定cpu的irq也不平衡。如果你想改变它,你可以做类似echo3>/proc/irq/24/smp_affinity的事情。这也是后面irqbalance用来调整中断的方法。irqbalance代码分析下面以v1.07为例进行分析。在irqbalance中,中断分为8类4种。/**IRQ类*/#defineIRQ_OTHER0#defineIRQ_LEGACY1#defineIRQ_SCSI2#defineIRQ_VIDEO3#defineIRQ_ETH4#defineIRQ_GBETH5#defineIRQ_10GBETH6#defineIRQ_VIRT_EVQPE7/**IR_TIR_T#defineIRQ_TYPEMSI_Types1#defineIRQ_TYPE_MSIX2#defineIRQ_TYPE_VIRT_EVENT3为什么有8个类?这个是根据pci设备初始化时注册的类型,可以通过下面的脚本查看[root@d2b9eb755bb1~]#foriin`ls/sys/bus/pci/devices/*/class`;doecho$((`cat$i`>>16));完成|排序-nu|wc-l8上面的类对应于使用以下数组的IRQ类:IRQ_SCSI,IRQ_OTHER,IRQ_OTHER,IRQ_OTHER,};MAX_CLASS=0x12为18。不同的class在平衡中断时作用域不同,有的在PACKAGE,有的在CACHE,有的在CORE。这种关系由以下数组转换:intmap_class_to_level[8]={BALANCE_PACKAGE,BALANCE_CACHE,BALANCE_CORE,BALANCE_CORE,BALANCE_CORE,BALANCE_CORE,BALANCE_CORE,BALANCE_CORE};irqbalance会根据cpu结构从上到下构建一个树结构,最上层是numa_nodes,从上到下依次是CPUpackages、Cachedomains和CPUcores。irqbalance的主要功能很简单,一个10s的周期,做以下事情:[1]清除上次的统计结果[2]分析中断情况[3]分析中断负载情况[4]计算如何平衡中断[5]执行上面指定的//irqbalance.cintmain(intargc,char**argv){//...//...while(keep_going){sleep_approx(SLEEP_INTERVAL);//10sclear_work_stats();parse_proc_interrupts();parse_proc_stat();//...//...calculate_placement();激活映射();//...}//...}中断最终都是运行在某个cpu上,所以有些中断分配在缓存和包层面,但最终还是运行在CPU上,执行的中断数每个CPU大致等于所有父节点逐级中断的平均数。然后用cpu的负载除以cpu平均处理的中断数,得到单位中断占用的负载,那么每个中断的负载就等于单位时间内新增中断数乘以单位中断占用负载。那么问题来了,负载如何计算呢?答案是通过/proc/stat文件的irq+softirq得到的。以cpu0为例,一个可能的数据如下:cpu02001184311258112897097106244597232182901048436000jiffies的个数(jiffies是内核中的一个全局变量,用来记录beats产生的次数系统的启动。在Linux中,一个节拍可以大致理解为操作系统进程调度的最小时间片。不同的Linux内核可能取值不同,一般在1ms到10ms之间)。上述字段含义如下:数值参数含义200118431用户在用户态的运行时间,不包括nice值是一个负过程。1258CPUtimenicenice值为负的进程占用CPU时间112897097CPUtimeincorestate1062445972idle除IO等待时间外的其他等待时间-详情请参考/proc目录。所以,cpu->last_load=(irq_load+softirq_load)。每个CORE的负载是它所附中断负载的总和,每个DOMAIN是包含的CORE的总和,每个PACKAGE包含的DOMAIN的总和就像树的层次结构一样计算。如何平衡上面得到的负载值呢?我将在下一篇文章中进行解释。待续...