
Linux PowerPC pseries 共享处理器 LPAR 的 VCPU 调度统计vcpudispatch_stats 深度指南【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux导读在 POWER 虚拟化环境中共享处理器 LPARShared Processor Logical Partition由 Power HypervisorPHYP将分区内的虚拟处理器vCPU动态调度到宿主机的物理处理器核心上执行。Hypervisor 会尽量把 vCPU 调度到其归属home物理芯片上但在负载压力、分区迁移等场景下vCPU 可能被调度到远离归属节点的芯片甚至跨 socket/drawer 执行导致 NUMA 访存延迟上升。本文基于 Linux 内核 pseries 平台实现完整讲解/proc/powerpc/vcpudispatch_stats与/proc/powerpc/vcpudispatch_stats_freq两个 procfs 接口的启用方法、8 个统计字段的精确含义、底层 DTLDispatch Trace Log处理机制与 NUMA 关联性associativity计算原理帮助你量化分区内 vCPU 调度的局部性为性能调优提供数据依据。一、背景为什么需要跟踪 vCPU 调度分布对于共享处理器 LPARPower Hypervisor 维护着一张 vCPU 到物理处理器芯片的相对静态映射关系。每个 vCPU 都有一个home node归属物理芯片Hypervisor 会优先将 vCPU 调度到其归属芯片上以充分利用芯片级缓存与本地内存访问路径获得良好的 NUMA 局部性。然而在以下场景中vCPU 可能会被调度到远离 home node 的物理芯片上归属芯片上的物理处理器全部繁忙Hypervisor 需要将 vCPU 临时溢出调度到其他芯片分区迁移、资源收缩或处理器热插拔导致映射关系变化多分区竞争导致全局调度压力增大。当 vCPU 频繁被调度到远端芯片时其访存路径跨越芯片互连甚至 socket/drawer 边界延迟显著增加。因此量化vCPU 实际被调度在哪里对于诊断共享处理器分区的性能抖动、验证 Hypervisor 调度局部性至关重要。这正是 vcpudispatch_stats.rst 文档所描述功能的价值所在。二、procfs 接口总览启用、关闭与采样频率该功能由 pseries 平台代码在启动时通过machine_device_initcall(pseries, vcpudispatch_stats_procfs_init)注册见 arch/powerpc/platforms/pseries/lpar.c并在共享处理器环境下创建两个 procfs 文件procfs 文件权限作用/proc/powerpc/vcpudispatch_stats0600仅 root写入1启用统计采集写入0关闭统计读取时输出每个 vCPU 的调度统计/proc/powerpc/vcpudispatch_stats_freq0600仅 root读取/设置每个 vCPU 的 DTL 日志处理频率次/秒默认 50从源码看这两个文件都通过proc_create(powerpc/vcpudispatch_stats, 0600, NULL, ...)创建在 procfs 根命名空间下0600权限意味着只有 root 用户可以读写这符合统计信息涉及系统调度细节的特性。2.1 启用统计$ sudo sh -c echo 1 /proc/powerpc/vcpudispatch_stats写入1后内核会依次完成四件事对应 vcpudispatch_stats_write 的cmd分支调用init_cpu_associativity()为每个可能的 vCPU 与物理 CPU 分配 associativity 缓冲lpar.c清空所有 CPU 的统计结构vcpu_disp_data并将last_disp_cpu初始化为-1表示尚无上一次调度记录通过set_global_dtl_mask(DTL_LOG_ALL)将每个 CPU 的dtl_enable_mask置为全部事件类型CEDE 等待、时间片抢占、缺页见 lpar.c注册 DTL workerdtl_worker_enable启动逐 CPU 的延迟工作队列开始消费 DTL 日志。写入时输入必须是 0 或 1其他值会被拒绝并输出提示please use 0 to disable or 1 to enable dispatch statistics。重复写入相同值会被幂等地忽略。2.2 关闭统计$ sudo sh -c echo 0 /proc/powerpc/vcpudispatch_stats关闭流程执行dtl_worker_disable()撤销 cpuhp 状态、释放 DTL 缓冲区、将全局dtl_mask复位非原生虚拟 CPU 计账时复位为 0、释放 associativity 缓冲并释放写锁。2.3 调整采样频率默认情况下每个 vCPU 的 DTL 日志每秒被处理 50 次以避免因处理不及时而丢失日志条目。该频率可通过第二个 procfs 文件调整# 查看当前频率 $ cat /proc/powerpc/vcpudispatch_stats_freq 50 # 调整为每秒 100 次 $ sudo sh -c echo 100 /proc/powerpc/vcpudispatch_stats_freq频率的合法取值范围为1到HZ内核时钟节拍数通常为 100 或 250超出范围的写入会被拒绝vcpudispatch_stats_freq_write。采样频率越高DTL 日志被消费得越及时、越不容易丢失条目但对应的每 CPU 延迟工作队列唤醒开销也越大需要根据分区繁忙程度权衡。三、统计输出格式8 个数字的精确语义统计启用后读取 procfs 文件即可得到结果$ sudo cat /proc/powerpc/vcpudispatch_stats输出中每一行对应一个 vCPU第一个字段是 vCPU 名称cpuN其后跟随 8 个数字。下面是文档中的完整示例输出cpu0 6839 4126 2683 30 0 6821 18 0 cpu1 2515 1274 1229 12 0 2509 6 0 cpu2 2317 1198 1109 10 0 2312 5 0 cpu3 2259 1165 1088 6 0 2256 3 0 cpu4 2205 1143 1056 6 0 2202 3 0 cpu5 2165 1121 1038 6 0 2162 3 0 cpu6 2183 1127 1050 6 0 2180 3 0 cpu7 2193 1133 1052 8 0 2187 6 0 cpu8 2165 1115 1032 18 0 2156 9 0 cpu9 2301 1252 1033 16 0 2293 8 0 cpu10 2197 1138 1041 18 0 2187 10 0 cpu11 2273 1185 1062 26 0 2260 13 0 cpu12 2186 1125 1043 18 0 2177 9 0 cpu13 2161 1115 1030 16 0 2153 8 0 cpu14 2206 1153 1033 20 0 2196 10 0 cpu15 2163 1115 1032 16 0 2155 8 03.1 第 1 个数字累计调度次数第 1 个数字如 cpu0 的6839是自统计启用以来该 vCPU 被调度的总次数total_disp。注意它不含第一次调度——内核在收到第一条 DTL 记录时只记录last_disp_cpu而不递增计数见 update_vcpu_disp_stat 中last_disp_cpu -1的 early return 分支。3.2 中间 4 个数字相对上次调度的离散程度接下来的 4 个数字描述该 vCPU 每次调度相对于上一次调度位置的离散情况序号字段源码字段名含义2same_cpu_disp被调度到与上次相同的物理 CPU或同核 sibling 线程的次数3same_chip_disp被调度到与上次不同的物理核心、但在同一物理芯片chip内的次数4diff_chip_disp被调度到与上次不同的物理芯片的次数5far_chip_disp被调度到与上次不同的 socket/drawer下一个 NUMA 边界的次数以内核源码为证update_vcpu_disp_stat()首先判断两次调度的物理 CPU 是否相同或互为同一核心的兄弟线程通过cpu_first_thread_sibling()比较否则调用cpu_relative_dispatch_distance()计算两个物理 CPU 的 associativity 相对距离距离 0/1/2 分别落入same_chip_disp/diff_chip_disp/far_chip_disp。3.3 最后 3 个数字相对 home node 的分布最后 3 个数字描述该 vCPU 的调度位置相对于其归属节点home node的关系序号字段源码字段名含义6numa_home_disp被调度在 home node归属芯片内的次数7numa_remote_disp被调度在归属节点之外、相邻节点neighbouring chip的次数8numa_far_disp被调度在更远节点NUMA distance 更大的次数这一组数据由cpu_home_node_dispatch_distance()计算取当前 vCPU 的 associativity通过hcall_vphn(cpu, VPHN_FLAG_VCPU, ...)获取与本次被调度物理 CPU 的 associativityVPHN_FLAG_PCPU调用cpu_relative_distance()得到距离值后分类计数。3.4 示例逐行解读以文档中的 cpu0 为例自启用统计以来共发生6839次调度其中4126次与上次调度在同一物理 CPU2683次换到了同芯片内的不同核心30次跨芯片调度相对上次0次跨 socket/drawer 调度相对上次就 home node 而言6821次调度发生在归属芯片内18次发生在归属节点之外相邻芯片0次落在更远的节点。可以看出该 vCPU 的调度局部性相当好99.7%6821/6839的调度都留在归属芯片内。而 cpu11 的numa_remote_disp 13、cpu10 的 10等则提示这些 vCPU 存在更多的跨节点溢出调度值得结合工作负载进一步分析。四、底层实现DTL 日志的采集流水线vCPU 调度统计并非内核主动轮询 Hypervisor而是基于 PowerPC 的Dispatch Trace LogDTL机制——Hypervisor 将每个物理处理器上的 vCPU 调度/抢占事件写入一段由内核注册的共享内存日志内核侧再周期性地消费这段日志。完整流水线如下Hypervisor 写入 DTL 缓冲区 │ ▼ 每个 CPU 的 delayed_workprocess_dtl_buffer 每秒触发 vcpudispatch_stats_freq 次 │ ▼ 逐条解析 dtl_entry取 processor_id │ ▼ update_vcpu_disp_stat()与上次调度位置、home node 比较 │ ▼ 累加到 per-CPU 的 struct vcpu_dispatch_data │ ▼ 读取 /proc/powerpc/vcpudispatch_stats 时经 seq_file 输出4.1 DTL 缓冲区与事件掩码每个 CPU 的 DTL 缓冲区为 4096 字节DISPATCH_LOG_BYTES见 arch/powerpc/include/asm/dtl.h由struct dtl_entry组成其中processor_id__be16大端字段即 Hypervisor 记录的实际调度物理 CPU 编号正是统计的核心输入。缓冲区在启用统计时通过alloc_dtl_buffers()从dtl_cache分配并调用register_dtl_buffer()通过register_dtl(hwcpu, __pa(dtl))超调用注册给 Hypervisor。事件掩码定义在 dtl.h#define DTL_LOG_CEDE 0x1 /* 自愿的虚拟处理器等待 */ #define DTL_LOG_PREEMPT 0x2 /* 时间片抢占 */ #define DTL_LOG_FAULT 0x4 /* 虚拟分区内存缺页 */ #define DTL_LOG_ALL (DTL_LOG_CEDE | DTL_LOG_PREEMPT | DTL_LOG_FAULT)启用统计时内核将全局掩码置为DTL_LOG_ALL即记录全部三类事件确保调度重新调度事件不因掩码而被 Hypervisor 过滤。4.2 每 CPU 的延迟工作队列统计的消费端是每个 CPU 上的一个struct dtl_worker内含delayed_work通过 cpuhp 回调dtl_worker_online()在 CPU 上线时注册并调度首次运行间隔为HZ / vcpudispatch_stats_freqlpar.c。process_dtl_buffer()每次执行时读取 VPAVirtual Processor Area中的dtl_idx与本地已消费索引dtl_entry_ridx比较若dtl_idx领先本地索引超过整个缓冲区长度N_DISPATCH_LOG说明缓冲已溢出内核记录丢失样本数并跳到最新位置lpar.c逐条取出dtl_entry用be16_to_cpu(dtle.processor_id)取出实际调度 CPU交给update_vcpu_disp_stat()累加统计处理完毕后在同一个 CPU 上重新调度下一次执行。worker 还具备自我保护如果它被迁移到了其他 CPUd-cpu ! smp_processor_id()会直接取消自己避免在错误的 CPU 上消费日志。4.3 per-CPU 统计数据结构统计的载体是 per-CPU 变量vcpu_disp_dataDEFINE_PER_CPU(struct vcpu_dispatch_data, vcpu_disp_data)其结构与输出字段一一对应lpar.cstruct vcpu_dispatch_data { int last_disp_cpu; /* 上次调度的物理 CPU-1 表示无记录 */ int total_disp; /* 累计调度次数 */ int same_cpu_disp; /* 与上次同一物理 CPU */ int same_chip_disp; /* 同芯片不同核心 */ int diff_chip_disp; /* 不同芯片 */ int far_chip_disp; /* 不同 socket/drawer */ int numa_home_disp; /* 在 home node 内 */ int numa_remote_disp; /* 在相邻节点 */ int numa_far_disp; /* 在更远节点 */ };输出侧vcpudispatch_stats_display()遍历for_each_online_cpu用seq_put_decimal_ull依次打印 8 个计数字段lpar.c。注意如果统计尚未启用读取文件只会输出一行off。五、NUMA 距离判定associativity 与 VPHN 超调用同一芯片不同芯片不同节点这些分类最终都由物理 CPU 与 vCPU 的associativity关联性数组决定。POWER 的 associativity 是一组从系统顶层到底层逐级缩放的域标识NUMA 距离通过比较两个数组的前缀得出。5.1 获取 associativityvCPU 侧hcall_vphn(cpu, VPHN_FLAG_VCPU, assoc[0])即虚拟处理器归属节点号码Virtual Processor Home Node超调用返回 vCPU 的关联性数组vphn.h物理 CPU 侧hcall_vphn(cpu, VPHN_FLAG_PCPU, assoc[0])。这两类信息在启用统计时分别缓存于vcpu_associativity与pcpu_associativity两个全局数组lpar.c按cpu / threads_per_core索引避免每条日志都重复发起超调用。5.2 相对距离计算cpu_relative_distance()arch/powerpc/mm/numa.c根据系统当前的 associativity 形式分发FORM1 关联性逐级比较两个数组的distance_ref_points指定索引处的域 ID第一个不相等的层级即距离__cpu_form1_relative_distance——距离 0 表示同级同芯片、1 表示跨一级跨芯片/节点、2 表示跨两级跨 socket/drawerFORM2 关联性先各自转换为 node ID再查numa_distance_table距离矩阵 LOCAL_DISTANCE返回 0、 REMOTE_DISTANCE返回 1、否则返回 2__cpu_form2_relative_distance。这解释了为什么第 5 个数与第 8 个数的语义存在细微差别前者衡量两次调度位置之间的相对距离与上次比后者衡量调度位置与 vCPU 归属节点之间的距离与 home 比但两者都复用同一套 0/1/2 三级距离模型。六、适用前提与使用限制仅限共享处理器 LPARprocfs 文件的创建受lppaca_shared_proc()保护lpar.c即只有分区运行在共享处理器模式下CONFIG_PPC_SPLPAR启用、VPA 声明 shared processor时接口才存在专用dedicated处理器分区无法使用。需要 root 权限两个文件权限均为 0600普通用户只能看到无权限。统计从启用时刻开始累计所有计数都是启用后累计的单调计数不是速率或百分比需要观察速率时应记录两个时间点的差值自行计算。DTL 缓冲溢出会丢样本若 Hypervisor 写入过快而 worker 消费不及缓冲溢出时内核会打印lost N DTL samples并跳过丢失部分lpar.c。遇到丢失时应调高vcpudispatch_stats_freq。首次调度不计数每个 vCPU 的第一条 DTL 记录仅用于建立last_disp_cpu基线不进入任何计数器因此total_disp会略小于真实的调度次数。距离计算失败会跳过若 associativity 获取失败如超调用返回错误对应样本不会计入任何分类字段仅打印限速的 debug 日志。七、典型使用场景7.1 验证 Hypervisor 调度局部性启用统计并让分区运行一段时间后读取输出计算 home node 命中率home_node_hit_ratio numa_home_disp / total_disp若命中率长期偏低、numa_remote_disp持续增长说明 vCPU 经常被溢出调度到相邻芯片可能与相邻分区争抢资源或归属芯片容量不足有关可作为向虚拟化平台团队反馈调度问题的量化依据。7.2 诊断性能抖动当共享处理器分区出现间歇性性能抖动且怀疑与调度迁移有关时对比抖动发生前后两个时间点导出的统计差值观察diff_chip_disp/far_chip_disp/numa_remote_disp增量是否显著上升可将NUMA 局部性劣化从CPU 争抢等候选原因中区分出来。7.3 评估采样开销vcpudispatch_stats_freq默认 50 次/秒。若在大型分区数百 vCPU上启用统计后发现额外的唤醒开销可适当调低频率下限 1若观察到 DTL 溢出丢样本则应调高频率。频率参数在运行时即可调整无需重启分区。结语/proc/powerpc/vcpudispatch_stats是 pseries 共享处理器分区上唯一的内核级 vCPU 调度位置统计接口。通过本文梳理的 8 字段语义、DTL 采集流水线与 associativity 距离模型你可以在真实环境中准确解读每一行输出将vCPU 被调度到了哪里这一虚拟化黑盒行为转化为可量化、可对比的性能数据。相关文档原文位于 Documentation/arch/powerpc/vcpudispatch_stats.rst核心实现位于 arch/powerpc/platforms/pseries/lpar.cNUMA 距离判定见 arch/powerpc/mm/numa.cDTL 数据结构定义见 arch/powerpc/include/asm/dtl.h感兴趣的读者可沿此路径深入阅读源码。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考