irqbalance 笔记
前置概念
需要提前掌握的一些概念:NUMA、软/硬中断、Cache
概述
irqbalance
主要用于多核处理器上分配硬中断从而提高性能。
The purpose of irqbalance is to distribute hardware interrupts across
processors on a multiprocessor system in order to increase performance.
从中断的角度均衡cpu负载。
Irqbalance is a daemon to help balance the cpu load generated by interrupts across all of a systems cpus.
IRQ是由系统设备生成的硬件信号,当多个设备同时发送IRQ请求时,将工作负载均匀分布在可用的CPU核心上是至关重要的。这就是 irqbalance
发挥作用的地方。
irqbalance
做的很通用,并不感知应用程序,很多场景不能达到很高的性能,而是尽量不劣化, 专注于中断,不会为了提高应用性能而做一些特殊功能
使用方法
service irqbalance start # 开启
service irqbalance stop # 关闭
# or
systemctl stop irqbalance.service
systemctl disable irqbalance.service
# 查看状态
[root@localhost ~]# service irqbalance status
Redirecting to /bin/systemctl status irqbalance.service
● irqbalance.service - irqbalance daemon
Loaded: loaded (/usr/lib/systemd/system/irqbalance.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2024-02-09 16:55:16 CST; 3 weeks 1 day ago
Docs: man:irqbalance(1)
https://github.com/Irqbalance/irqbalance
Process: 832 ExecStart=/usr/sbin/irq_balancer (code=exited, status=0/SUCCESS)
Main PID: 846 (irqbalance)
Tasks: 2 (limit: 21409)
Memory: 536.0K
CGroup: /system.slice/irqbalance.service
└─ 846 /usr/sbin/irqbalance --pid=/var/run/irqbalance.pid
2月 09 16:55:16 localhost systemd[1]: Starting irqbalance daemon...
2月 09 16:55:16 localhost systemd[1]: Started irqbalance daemon.
[root@localhost ~]# ps aux | grep irqb
root 846 0.0 0.0 79352 1680 ? Ssl 2月18 0:42 /usr/sbin/irqbalance --pid=/var/run/irqbalance.pid
root 52875 0.0 0.0 21980 2292 pts/0 S+ 18:21 0:00 grep --color=auto irqb
命令选项
[root@localhost ~]# irqbalance -h
irqbalance: invalid option -- 'h'
irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j]
[--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>] [--banmod= | -m <module>] [--policyscript= | -l <script>]
[--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--migrateval= | -e <n>
常用的
-o, --oneshot : 执行一次后退出守护进程
-d, --debug : 打印一些运行信息
-j, --journal : 系统日志输出
-p,--powerthresh=<threshold> : 给省电模式设置阈值
-i, --banirq=<irqnum> : 设置后 irqbalance 不会影响对应irq的亲和性
-t, --interval=<time> : 默认10s, 按此间隔循环刷新亲和性
配置文件
/etc/sysconfig/irqbalance
IRQBALANCE_BANNED_CPUS : 配置禁用中断的CPU,配置后 irqbalance 不会将中断迁移至对应核
代码实现
源码:https://github.com/Irqbalance/irqbalance
依赖的系统信息
主处理在 irqbalance.c
。
-
build_numa_node_list
:对应的obj_type
为OBJ_TYPE_NODE
- 解析
/sys/devices/system/node/node0/cpumap
获得各个numa
节点的cpumap
,
- 解析
-
parse_cpu_tree
:对应的obj_type
为OBJ_TYPE_CPU
-
解析
/sys/devices/system/cpu/online
-
解析
/sys/devices/system/cpu/cpu0/topology/physical_package_id
-
解析
/sys/devices/system/cpu/cpu0/topology/core_siblings
-
add_cpu_to_cache_domain
: 对应的obj_type
为OBJ_TYPE_CACHE
- 解析
/sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_map
- index0 : L1 data缓存
- index1 : L1 Instruction缓存
- index2 : L2 缓存
- index3 : L3 缓存
- 解析
-
add_cache_domain_to_package
:对应的obj_type
为OBJ_TYPE_PACKAGE
-
-
代码中搜索
obj_type =
观察如何划分四个维度的信息 -
rebuild_irq_db
/proc/interrupts
/proc/irq/%i/node
/sys/bus/pci/devices/[]/msi_irqs
- 找到每个设备有哪些中断
-
parse_proc_stat
: 计算负载/proc/stat
cpu->last_load = (irq_load + softirq_load);
// 软中断+硬中断
-
activate_mappings
通过动态调整/proc/irq/[*]/smp_affinity
的值,进而改变硬中断发生的位置,所以要让硬中断固定在某个核上,则需要关闭irqbalance
服务 -
只会修改中断,而不会迁移线程
Performance & Power-save
- Performance mode , 会将中断尽可能均匀地分发给各个 CPU core,以充分利用 CPU 多核,提升性能。
- Power-save mode ,当系统负载比较低时,会将中断迁移至1个cpu,以保证其它空闲 CPU 的睡眠时间,降低能耗。
默认情况下是处于Performance mode,通过-p,--powerthresh=<threshold>
设置节能门限,默认ULONG_MAX
,代码片段如下
unsigned long power_thresh = ULONG_MAX;
...
if (!info.num_over && (info.num_under >= power_thresh) && info.powersave) {
log(TO_ALL, LOG_INFO, "cpu %d entering powersave mode\n", info.powersave->number);
info.powersave->powersave_mode = 1;
数据结构
拓扑结构
enum obj_type_e {
OBJ_TYPE_CPU,
OBJ_TYPE_CACHE,
OBJ_TYPE_PACKAGE,
OBJ_TYPE_NODE
};
这里的拓扑不是 irqbalance
创造的,而是系统本身的属性,比如用 lstopo
命令查看
Linux中的lstopo命令(详细指南)
IRQ Classes
types.h
#define IRQ_NODEF -1
#define IRQ_OTHER 0
#define IRQ_LEGACY 1
#define IRQ_SCSI 2
#define IRQ_VIDEO 3
#define IRQ_ETH 4
#define IRQ_GBETH 5
#define IRQ_10GBETH 6
#define IRQ_VIRT_EVENT 7
和 /sys/bus/pci/devices/*/class
对应
IRQ Types
#define IRQ_TYPE_LEGACY 0
#define IRQ_TYPE_MSI 1
#define IRQ_TYPE_MSIX 2
#define IRQ_TYPE_VIRT_EVENT 3
均衡策略
#define BALANCE_NONE 0
#define BALANCE_PACKAGE 1
#define BALANCE_CACHE 2
#define BALANCE_CORE 3
class 和 策略的映射关系
static int map_class_to_level[8] =
{ BALANCE_PACKAGE, BALANCE_CACHE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE };
class | level |
---|---|
IRQ_OTHER | BALANCE_PACKAGE |
IRQ_LEGACY | BALANCE_CACHE |
IRQ_SCSI | BALANCE_CORE |
IRQ_VIDEO | BALANCE_CORE |
IRQ_VIDEO | BALANCE_CORE |
IRQ_ETH | BALANCE_CORE |
IRQ_GBETH | BALANCE_CORE |
IRQ_10GBETH | BALANCE_CORE |
IRQ_VIRT_EVENT | BALANCE_CORE |
维护中断的数据结构
struct irq_info {
int irq;
int class;
int type;
int level;
int flags;
struct topo_obj *numa_node; //中断当前所在node节点对应的object
cpumask_t cpumask;
uint64_t irq_count;
uint64_t last_irq_count;
uint64_t load;
int moved;
int existing;
struct topo_obj *assigned_obj; //中断被分配到节点对应的object
char *name;
};
- irq_count 表示本次统计irq中断在各个cpu上产生的中断次数之和。
- last_irq_count表示上次统计irq中断在各个cpu上的产生的中断次数之和。
维护拓扑的数据结构:
struct topo_obj {
uint64_t load;
uint64_t last_load;
uint64_t irq_count;
enum obj_type_e obj_type;
int number;
int powersave_mode;
cpumask_t mask;
GList *interrupts;
struct topo_obj *parent;
GList *children;
GList *numa_nodes;
GList **obj_type_list;
};
可以看出 topo_obj
是分层的(一层包含下一层),每层有一个 obj_type
拓扑类型。
从网上资料来看,obj_type
类型间关系不一定是唯一的,一个 package 可能有多个 node ,一个node上可能有多个 package。
参考linux 用户空间优化中断 irqbalance机制 简介
参考
irqbalance(1) - Linux man page
https://github.com/Irqbalance/irqbalance
Need for the irqbalance Command in Linux on Modern Hardware
深入代码详谈irqbalance
linux 用户空间优化中断 irqbalance机制 简介
深度剖析告诉你irqbalance有用吗?