当前位置: 首页 > article >正文

Linux CFS 的 throttled_cfs_rq:被限流任务组的管理与恢复

一、简介在现代云计算和容器化环境中CPU资源的公平分配与限制是系统稳定性的关键保障。Linux内核的CFSCompletely Fair Scheduler带宽控制机制通过cpu.cfs_quota_us和cpu.cfs_period_uscgroup v2中统一为cpu.max为进程组提供硬性的CPU使用上限。当一个cgroup内的进程在指定周期内消耗完所有配额时内核会触发限流throttle机制将该cgroup关联的cfs_rqCFS运行队列标记为受限状态并将其加入全局的throttled_cfs_rq链表进行管理。掌握throttled_cfs_rq的管理与恢复机制对于以下场景至关重要云原生调度理解Kubernetes中CPU limit的底层实现原理性能调优诊断容器CPU throttling导致的延迟问题内核开发参与调度子系统的优化与bug修复学术研究分析实时系统的资源隔离与调度算法本文将深入解析内核源码通过实际案例演示限流触发、队列管理、配额恢复的全过程帮助读者建立对CFS带宽控制机制的系统性认知。二、核心概念2.1 带宽控制基础术语术语说明对应cgroup接口Period资源核算的时间窗口默认100mscpu.cfs_period_us/cpu.max第二个值Quota周期内允许使用的CPU时间-1表示无限制cpu.cfs_quota_us/cpu.max第一个值Runtime全局时间池的剩余配额内核内部维护Throttle配额耗尽后强制暂停调度cpu.stat中的throttled统计Unthrottle新周期开始后恢复调度自动或手动触发2.2 关键数据结构CFS带宽控制涉及两个核心结构体分别代表中心端任务组级和节点端CPU级// 中心端task_group级别的带宽管理 struct cfs_bandwidth { raw_spinlock_t lock; // 保护全局时间池的锁 ktime_t period; // 周期时长 u64 quota; // 周期配额 u64 runtime; // 全局时间池剩余时间 u64 runtime_expires;// 当前周期到期时间 struct hrtimer period_timer; // 周期定时器 struct hrtimer slack_timer; // 剩余时间回收定时器 struct list_head throttled_cfs_rq; // 被限流的cfs_rq链表核心 int nr_periods; // 周期计数 int nr_throttled; // 限流次数统计 u64 throttled_time; // 累计限流时间 bool distribute_running; // 是否正在分发时间 }; // 节点端per-CPU的CFS运行队列 struct cfs_rq { // ... 其他CFS字段 ... int runtime_enabled; // 是否启用带宽控制 u64 runtime_expires; // 本地到期时间 s64 runtime_remaining; // 本地剩余时间片 u64 throttled_clock; // 开始限流的时间戳 int throttled; // 限流状态标志 int throttle_count; // 层级限流计数 struct list_head throttled_list; // 用于挂入throttled_cfs_rq链表 };关键理解throttled_cfs_rq链表是连接中心端与节点端的桥梁——当某个CPU上的cfs_rq耗尽本地时间且无法从全局池获取配额时就会被挂入该链表等待周期重置后的恢复。2.3 限流与恢复的触发条件触发限流的条件需同时满足cfs_rq-runtime_remaining 0本地时间耗尽__assign_cfs_rq_runtime()返回false无法从全局池申请到配额当前不在限流状态!cfs_rq_throttled(cfs_rq)触发恢复的条件period_timer到期全局时间池runtime重置为quotadistribute_cfs_runtime()为cfs_rq分配了正数时间片或slack_timer回收了足够时间并触发异步恢复三、环境准备3.1 软硬件环境要求项目要求操作系统Linux 5.4推荐6.6 LTS或更新版本内核配置CONFIG_CFS_BANDWIDTHy、CONFIG_CGROUPSy文件系统cgroup v2挂载或v1的cpu控制器开发工具gcc、bpftrace、perf、ftrace权限root或具有CAP_SYS_ADMIN能力3.2 验证环境支持#!/bin/bash # 文件名check_env.sh # 功能验证系统是否支持CFS带宽控制 echo CFS Bandwidth Control 环境检查 # 1. 检查内核配置 echo [1/5] 检查内核配置... if zgrep -q CONFIG_CFS_BANDWIDTHy /proc/config.gz 2/dev/null || \ grep -q CONFIG_CFS_BANDWIDTHy /boot/config-$(uname -r) 2/dev/null; then echo ✅ 内核已启用CFS_BANDWIDTH else echo ❌ 内核未启用CFS_BANDWIDTH需要重新编译内核 exit 1 fi # 2. 检查cgroup挂载 echo [2/5] 检查cgroup挂载... if mount | grep -q cgroup2; then echo ✅ cgroup v2已挂载 CGROUP_Vv2 elif mount | grep -q cgroup.*cpu; then echo ✅ cgroup v1 (cpu控制器)已挂载 CGROUP_Vv1 else echo ❌ cgroup未正确挂载 exit 1 fi # 3. 检查带宽控制接口 echo [3/5] 检查带宽控制接口... if [ $CGROUP_V v2 ]; then if [ -f /sys/fs/cgroup/cpu.max ]; then echo ✅ v2 cpu.max接口存在 fi else if [ -d /sys/fs/cgroup/cpu ]; then echo ✅ v1 cpu控制器存在 fi fi # 4. 检查内核参数 echo [4/5] 检查可调参数... if [ -f /proc/sys/kernel/sched_cfs_bandwidth_slice_us ]; then echo ✅ sched_cfs_bandwidth_slice_us: $(cat /proc/sys/kernel/sched_cfs_bandwidth_slice_us) us else echo ⚠️ 内核参数接口不存在可能为旧版本 fi # 5. 检查调试工具 echo [5/5] 检查调试工具... command -v bpftrace /dev/null 21 echo ✅ bpftrace已安装 || echo ⚠️ bpftrace未安装 command -v perf /dev/null 21 echo ✅ perf已安装 || echo ⚠️ perf未安装 echo echo 环境检查完成 3.3 测试环境搭建# 创建测试cgroupv2示例 sudo mkdir -p /sys/fs/cgroup/test_throttle echo cpu | sudo tee /sys/fs/cgroup/cgroup.subtree_control # 设置严格限制每100ms只能使用50ms CPU0.5核 echo 50000 100000 | sudo tee /sys/fs/cgroup/test_throttle/cpu.max # 创建CPU密集型测试程序 cat /tmp/cpu_burn.c EOF #include stdio.h #include unistd.h #include sys/types.h int main() { printf(PID: %d\n, getpid()); volatile long counter 0; while (1) { counter; // 每1亿次循环打印一次避免输出过多 if (counter % 100000000 0) { printf(Counter: %ld\n, counter); } } return 0; } EOF gcc -o /tmp/cpu_burn /tmp/cpu_burn.c -O2四、应用场景在多租户容器平台中CFS带宽控制与throttled_cfs_rq机制发挥着关键的资源隔离作用。假设一个场景某云服务商的Kubernetes集群运行着电商应用延迟敏感和日志处理批处理两类工作负载。平台管理员为每个Namespace设置CPU limit如电商Pod限制为1核cpu.max 100000 100000日志处理限制为0.5核。当电商应用遭遇流量洪峰时其CPU使用迅速达到limit阈值此时内核触发throttle机制该Pod对应cgroup的cfs_rq被移出调度红黑树加入throttled_cfs_rq链表进程被强制等待。这虽然保护了节点其他租户但会导致请求延迟飙升。通过理解throttled_cfs_rq的恢复时机下一个period开始管理员可以调整period长度如从100ms改为10ms来缩短冷冻期或开启cpu.max.burst允许短期突发。同时监控cpu.stat中的throttled_usec指标可以量化throttle对业务的影响指导资源limit的合理设置。五、实际案例与步骤5.1 案例一观察throttle触发与队列管理目标观察cfs_rq被加入throttled_cfs_rq链表的全过程。#!/bin/bash # 文件名case1_throttle_trigger.sh # 功能演示throttle触发过程 set -e CGROUP_PATH/sys/fs/cgroup/test_throttle TEST_PROG/tmp/cpu_burn echo 案例1Throttle触发与队列管理观察 # 步骤1创建cgroup并设置严格限制0.1核 echo [步骤1] 创建cgroup设置quota10ms/period100ms... sudo mkdir -p $CGROUP_PATH 2/dev/null || true echo 10000 100000 | sudo tee $CGROUP_PATH/cpu.max echo 1 | sudo tee $CGROUP_PATH/cpu.weight # 步骤2启动CPU密集型进程并加入cgroup echo [步骤2] 启动测试进程... $TEST_PROG PID$! sleep 1 # 等待进程启动 echo $PID | sudo tee $CGROUP_PATH/cgroup.procs echo 测试进程PID: $PID已加入cgroup # 步骤3监控throttle统计 echo [步骤3] 监控throttle状态持续10秒... echo 时间戳 | nr_periods | nr_throttled | throttled_time for i in {1..10}; do STAT$(cat $CGROUP_PATH/cpu.stat 2/dev/null | grep -E nr_periods|throttled | tr \n ) echo $(date %H:%M:%S) | $STAT sleep 1 done # 步骤4使用perf观察调度事件如果perf可用 if command -v perf /dev/null 21; then echo echo [步骤4] 使用perf采样sched_stat_throttled事件5秒... sudo perf stat -e sched:sched_stat_throttled -p $PID -- sleep 5 21 || true fi # 清理 echo [清理] 终止测试进程... kill $PID 2/dev/null || true wait $PID 2/dev/null || true echo echo 观察要点 echo 1. nr_throttled应随时间增加表示发生多次限流 echo 2. throttled_time表示累计被限流的时间纳秒 echo 3. 当quota(10ms)耗尽后进程必须等待下一个period(100ms)开始代码说明cpu.max 10000 100000表示每100ms周期内只能使用10ms CPU10%限制cpu.stat文件提供nr_periods周期计数、nr_throttled限流次数、throttled_usec累计限流时间三个关键指标5.2 案例二分析内核throttle路径目标通过ftrace跟踪throttle_cfs_rq和unthrottle_cfs_rq的调用。#!/bin/bash # 文件名case2_ftrace_throttle.sh # 功能使用ftrace跟踪throttle/unthrottle路径 set -e echo 案例2内核throttle路径跟踪 # 步骤1挂载debugfs sudo mount -t debugfs none /sys/kernel/debug 2/dev/null || true # 步骤2启用sched相关tracepoint echo [步骤1] 启用sched:sched_stat_throttled tracepoint... echo 1 | sudo tee /sys/kernel/debug/tracing/events/sched/sched_stat_throttled/enable 2/dev/null || { echo ⚠️ tracepoint不可用尝试使用kprobe... # 备用方案使用kprobe跟踪throttle_cfs_rq sudo sh -c echo p:throttle_enter throttle_cfs_rq /sys/kernel/debug/tracing/kprobe_events sudo sh -c echo p:throttle_exit unthrottle_cfs_rq /sys/kernel/debug/tracing/kprobe_events echo 1 | sudo tee /sys/kernel/debug/tracing/events/kprobes/throttle_enter/enable echo 1 | sudo tee /sys/kernel/debug/tracing/events/kprobes/throttle_exit/enable } # 步骤3清空trace buffer echo | sudo tee /sys/kernel/debug/tracing/trace # 步骤4启动测试负载 echo [步骤2] 启动测试负载... CGROUP_PATH/sys/fs/cgroup/test_throttle2 sudo mkdir -p $CGROUP_PATH 2/dev/null || true echo cpu | sudo tee /sys/fs/cgroup/cgroup.subtree_control /dev/null 21 || true echo 20000 100000 | sudo tee $CGROUP_PATH/cpu.max # 20%限制 # 启动4个CPU密集型线程 for i in {1..4}; do taskset -c 0 /tmp/cpu_burn echo $! | sudo tee $CGROUP_PATH/cgroup.procs /dev/null done BG_PIDS$! # 步骤5采集trace echo [步骤3] 采集trace数据5秒... sleep 5 sudo cat /sys/kernel/debug/tracing/trace | head -100 /tmp/throttle_trace.txt echo Trace数据已保存到/tmp/throttle_trace.txt # 步骤6分析trace echo [步骤4] 分析trace数据... echo --- throttle_cfs_rq调用统计 --- grep -c throttle_cfs_rq /tmp/throttle_trace.txt 2/dev/null || echo 0 echo --- unthrottle_cfs_rq调用统计 --- grep -c unthrottle_cfs_rq /tmp/throttle_trace.txt 2/dev/null || echo 0 # 显示部分原始trace echo --- 原始trace样本前20行--- head -20 /tmp/throttle_trace.txt # 清理 echo [清理] 停止跟踪... kill $BG_PIDS 2/dev/null || true echo 0 | sudo tee /sys/kernel/debug/tracing/events/sched/sched_stat_throttled/enable 2/dev/null || true echo | sudo tee /sys/kernel/debug/tracing/trace sudo rmdir $CGROUP_PATH 2/dev/null || true5.3 案例三period_timer与配额恢复机制目标观察period_timer到期后如何从throttled_cfs_rq链表恢复cfs_rq。/* * 内核关键函数解析do_sched_cfs_period_timer * 位于 kernel/sched/fair.c * * 这是周期定时器到期时执行的函数负责 * 1. 重置全局时间池runtime * 2. 遍历throttled_cfs_rq链表分发时间 * 3. 调用unthrottle_cfs_rq解除限流 */ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun) { int throttled; // 1. 检查是否配置了带宽限制 if (cfs_b-quota RUNTIME_INF) goto out_deactivate; // 无限制直接退出 // 2. 检查是否有被限流的cfs_rq throttled !list_empty(cfs_b-throttled_cfs_rq); cfs_b-nr_periods overrun; // 累计周期数 // 3. 重置全局时间池将runtime设为quota __refill_cfs_bandwidth_runtime(cfs_b); // 4. 如果没有被限流的队列且处于idle状态停掉定时器 if (cfs_b-idle !throttled) goto out_deactivate; if (!throttled) { cfs_b-idle 1; return 0; } // 5. 统计限流周期数 cfs_b-nr_throttled overrun; // 6. 关键循环分发时间并解除限流 while (throttled cfs_b-runtime 0) { raw_spin_unlock(cfs_b-lock); // distribute_cfs_runtime遍历throttled_cfs_rq链表 throttled distribute_cfs_runtime(cfs_b); raw_spin_lock(cfs_b-lock); } cfs_b-idle 0; return 0; } /* * distribute_cfs_runtime分发时间给被限流的cfs_rq * 遍历throttled_cfs_rq链表为每个cfs_rq分配runtime_remaining */ static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b) { struct cfs_rq *cfs_rq; u64 runtime, remaining 1; rcu_read_lock(); // 遍历throttled_cfs_rq链表RCU保护 list_for_each_entry_rcu(cfs_rq, cfs_b-throttled_cfs_rq, throttled_list) { struct rq *rq rq_of(cfs_rq); struct rq_flags rf; rq_lock(rq, rf); if (!cfs_rq_throttled(cfs_rq)) goto next; // 已经被解除限流跳过 // 计算需要分配的时间当前负值1ns缓冲 runtime -cfs_rq-runtime_remaining 1; if (runtime remaining) runtime remaining; remaining - runtime; // 分配时间片 cfs_rq-runtime_remaining runtime; cfs_rq-runtime_expires cfs_b-runtime_expires; // 如果分配后时间片为正解除限流 if (cfs_rq-runtime_remaining 0) unthrottle_cfs_rq(cfs_rq); next: rq_unlock(rq, rf); if (!remaining) break; // 全局时间池耗尽 } rcu_read_unlock(); return remaining; }测试脚本#!/bin/bash # 文件名case3_period_timer.sh # 功能观察period_timer与配额恢复 echo 案例3Period Timer与配额恢复机制 # 调整slice大小以观察效果可选 # echo 10000 | sudo tee /proc/sys/kernel/sched_cfs_bandwidth_slice_us CGROUP_PATH/sys/fs/cgroup/test_period sudo mkdir -p $CGROUP_PATH 2/dev/null || true echo cpu | sudo tee /sys/fs/cgroup/cgroup.subtree_control /dev/null 21 || true # 设置周期为500ms配额为100ms20%限制便于观察 echo 100000 500000 | sudo tee $CGROUP_PATH/cpu.max echo [步骤1] 配置period500ms, quota100ms (20% CPU) # 启动测试进程 taskset -c 0 /tmp/cpu_burn PID$! sleep 1 echo $PID | sudo tee $CGROUP_PATH/cgroup.procs /dev/null echo [步骤2] 监控配额恢复过程每100ms采样一次持续5秒... # 使用bpftrace监控throttle/unthrottle事件如果可用 if command -v bpftrace /dev/null 21; then sudo timeout 5 bpftrace -e tracepoint:sched:sched_stat_throttled { printf(THROTTLE: pid%d, delay%llu us\n, pid, args-delay / 1000); } 2/dev/null || true else # 备用通过cpu.stat观察 for i in {1..50}; do THROTTLED$(grep nr_throttled $CGROUP_PATH/cpu.stat | awk {print $2}) TIME$(grep throttled_usec $CGROUP_PATH/cpu.stat | awk {print $2}) echo $(date %s.%N) nr_throttled$THROTTLED throttled_usec$TIME sleep 0.1 done fi kill $PID 2/dev/null || true sudo rmdir $CGROUP_PATH 2/dev/null || true echo echo 分析要点 echo 1. 每500ms period到期nr_throttled会增加 echo 2. throttled_usec的增量反映实际被限流的时间 echo 3. 如果quota(100ms)在周期内耗尽剩余400ms处于throttle状态5.4 案例四slack_timer与剩余时间回收目标理解slack_timer如何回收未使用的runtime并触发异步恢复。/* * __return_cfs_rq_runtime将cfs_rq的剩余时间返还给全局池 * 当任务出队如睡眠、退出时调用 */ static void __return_cfs_rq_runtime(struct cfs_rq *cfs_rq) { struct cfs_bandwidth *cfs_b tg_cfs_bandwidth(cfs_rq-tg); // 保留最小时间片默认1ms避免频繁申请 s64 slack_runtime cfs_rq-runtime_remaining - min_cfs_rq_runtime; if (slack_runtime 0) return; // 剩余时间太少不回收 raw_spin_lock(cfs_b-lock); if (cfs_b-quota ! RUNTIME_INF) { cfs_b-runtime slack_runtime; // 返还全局池 // 如果全局池有足够时间且有被限流的cfs_rq启动slack_timer if (cfs_b-runtime sched_cfs_bandwidth_slice() !list_empty(cfs_b-throttled_cfs_rq)) start_cfs_slack_bandwidth(cfs_b); } raw_spin_unlock(cfs_b-lock); cfs_rq-runtime_remaining - slack_runtime; }测试脚本#!/bin/bash # 文件名case4_slack_timer.sh # 功能演示slack_timer的剩余时间回收 echo 案例4Slack Timer与剩余时间回收 CGROUP_PATH/sys/fs/cgroup/test_slack sudo mkdir -p $CGROUP_PATH 2/dev/null || true echo cpu | sudo tee /sys/fs/cgroup/cgroup.subtree_control /dev/null 21 || true # 设置限制200ms/500ms40% echo 200000 500000 | sudo tee $CGROUP_PATH/cpu.max echo [步骤1] 启动间歇性CPU负载工作2秒睡眠2秒... # 创建间歇性负载脚本 cat /tmp/intermittent_load.sh EOF #!/bin/bash while true; do # CPU密集型工作2秒 timeout 2 taskset -c 0 /tmp/cpu_burn /dev/null 21 PID$! wait $PID 2/dev/null # 睡眠2秒让出CPU sleep 2 done EOF chmod x /tmp/intermittent_load.sh # 启动测试 taskset -c 0 /tmp/intermittent_load.sh BG_PID$! sleep 1 echo $BG_PID | sudo tee $CGROUP_PATH/cgroup.procs /dev/null echo [步骤2] 监控回收效果持续20秒... echo 时间 | 全局runtime(估算) | throttled次数 | 限流时间(us) for i in {1..20}; do # 读取统计 STATS$(cat $CGROUP_PATH/cpu.stat 2/dev/null) THROTTLED$(echo $STATS | grep nr_throttled | awk {print $2}) TIME$(echo $STATS | grep throttled_usec | awk {print $2}) echo $(date %H:%M:%S) | N/A | $THROTTLED | $TIME sleep 1 done kill $BG_PID 2/dev/null || true pkill -f cpu_burn 2/dev/null || true sudo rmdir $CGROUP_PATH 2/dev/null || true echo echo 原理解析 echo 当测试进程sleep时其cfs_rq的runtime_remaining会被部分返还到全局池 echo 如果此时throttled_cfs_rq链表非空slack_timer会被启动 echo slack_timer到期后会调用distribute_cfs_runtime尝试提前解除限流六、常见问题与解答Q1为什么设置了quota但进程仍然使用了超过限制的CPU原因分析Burst机制cgroup v2的cpu.max.burst允许短期突破限制统计粒度cpu.stat的统计可能因内核版本而异多核聚合quota是跨CPU聚合的多核场景下单核可能短暂超限诊断方法# 检查是否启用了burstv2 cat /sys/fs/cgroup/$CGROUP/cpu.max.burst # 查看详细统计 watch -n 1 cat /sys/fs/cgroup/$CGROUP/cpu.statQ2throttled_cfs_rq链表中的cfs_rq是如何排序的解答根据内核源码插入位置取决于distribute_running标志如果正在分发时间distribute_running1插入链表头部——避免当前分发过程看到新加入的cfs_rq否则插入链表尾部——保证FIFO顺序防止饥饿// 来自throttle_cfs_rq函数 if (cfs_b-distribute_running) list_add_rcu(cfs_rq-throttled_list, cfs_b-throttled_cfs_rq); else list_add_tail_rcu(cfs_rq-throttled_list, cfs_b-throttled_cfs_rq);Q3如何降低throttle带来的延迟影响解决方案缩短period减小cpu.cfs_period_usv1或使用更短的period值v2但会增加调度开销增大quota确保quota足够覆盖突发流量启用burstv2echo 50000 cpu.max.burst允许50ms的突发调整slice增大sched_cfs_bandwidth_slice_us默认5ms减少申请频率Q4内核6.x版本对throttle机制有何改进改进点基于内核6.6源码异步unthrottle引入unthrottle_cfs_rq_async在非本地CPU上通过throttled_csd_list延迟处理减少锁竞争Task-based throttleRFC补丁提出将throttle延迟到用户态返回时执行避免内核态持有资源被限流PELT时钟冻结优化更精确地处理限流期间的负载计算Q5如何监控throttle事件对业务的影响监控脚本#!/bin/bash # 实时监控cgroup的throttle情况 CGROUP$1 INTERVAL${2:-1} if [ -z $CGROUP ]; then echo 用法: $0 cgroup路径 [采样间隔秒] exit 1 fi echo 时间,周期数,限流次数,限流时间(us),限流占比(%) PREV_THROTTLED0 PREV_TIME0 while true; do STATS$(cat $CGROUP/cpu.stat) PERIODS$(echo $STATS | grep nr_periods | awk {print $2}) THROTTLED$(echo $STATS | grep nr_throttled | awk {print $2}) TIME$(echo $STATS | grep throttled_usec | awk {print $2}) if [ -n $PREV_TIME ] [ $PREV_TIME -gt 0 ]; then DELTA_TIME$((TIME - PREV_TIME)) DELTA_PERIOD$((PERIODS - PREV_PERIODS)) if [ $DELTA_PERIOD -gt 0 ]; then # 计算限流占比假设period为100ms THROTTLE_PCT$(echo scale2; $DELTA_TIME / ($DELTA_PERIOD * 100000) * 100 | bc) echo $(date %H:%M:%S),$PERIODS,$THROTTLED,$TIME,$THROTTLE_PCT% fi fi PREV_PERIODS$PERIODS PREV_THROTTLED$THROTTLED PREV_TIME$TIME sleep $INTERVAL done七、实践建议与最佳实践7.1 调试技巧1. 使用ftrace跟踪调度事件# 启用调度跟踪 sudo mount -t debugfs none /sys/kernel/debug echo 1 /sys/kernel/debug/tracing/events/sched/sched_stat_throttled/enable cat /sys/kernel/debug/tracing/trace_pipe | grep throttled2. 使用bpftrace获取细粒度统计sudo bpftrace -e tracepoint:sched:sched_stat_throttled { throttle_ns[comm] hist(args-delay); } 3. 内核日志分析# 开启调度调试需重新编译内核开启CONFIG_SCHED_DEBUG echo Y /sys/kernel/debug/sched/debug7.2 性能优化建议1. 合理选择period长度场景推荐period说明低延迟应用Web服务10-50ms快速恢复减少throttle延迟批处理任务100-1000ms减少上下文切换提高吞吐混合负载100ms默认平衡延迟与开销2. 避免quota碎片化# 不推荐quota 1ms调度器开销占比过高 echo 1000 cpu.cfs_quota_us # 推荐最小quota至少为1ms最好是slice的整数倍 echo 10000 cpu.cfs_quota_us # 至少10ms3. 结合cpuset优化# 将任务绑定到特定CPU减少缓存失效 sudo sh -c echo 0-3 /sys/fs/cgroup/cpuset/mygroup/cpuset.cpus7.3 生产环境配置模板Web服务容器延迟敏感# cgroup v2配置 echo 100000 100000 cpu.max # 基础限制1核 echo 100000 cpu.max.burst # 允许突发1核 echo 100 cpu.weight # 相对权重 echo 0-3 cpuset.cpus # 绑定到前4核批处理任务吞吐量优先# cgroup v1配置 echo 1000000 cpu.cfs_period_us # 1秒周期 echo 800000 cpu.cfs_quota_us # 80% CPU echo 0 cpu.cfs_burst_us # 禁用burst严格限制7.4 内核参数调优# 调整CFS带宽控制slice大小默认5000us # 增大可减少锁竞争但可能增加单核分配延迟 echo 10000 /proc/sys/kernel/sched_cfs_bandwidth_slice_us # 查看当前配置 sysctl kernel.sched_cfs_bandwidth_slice_us八、总结与应用场景本文深入剖析了Linux CFS调度器中throttled_cfs_rq链表的管理与恢复机制核心要点包括限流触发当cfs_rq的runtime_remaining耗尽且无法从全局池cfs_b-runtime申请配额时throttle_cfs_rq()将cfs_rq加入throttled_cfs_rq链表并设置throttled1队列管理throttled_cfs_rq链表采用RCU保护插入位置根据distribute_running标志决定头部或尾部保证分发过程的正确性与公平性配额恢复period_timer到期后do_sched_cfs_period_timer()重置全局时间池调用distribute_cfs_runtime()遍历链表分发时间片时间片为正的cfs_rq通过unthrottle_cfs_rq()恢复调度异步优化内核6.x引入unthrottle_cfs_rq_async和throttled_csd_list减少跨CPU解除限流时的锁竞争应用场景回顾云原生资源隔离Kubernetes CPU limit的底层实现依赖本文所述机制理解其原理有助于合理设置limit避免过度限流实时系统调优通过调整period/quota参数在延迟与吞吐量之间取得平衡性能问题诊断利用cpu.stat和ftrace定位throttle导致的延迟问题建议读者在实际项目中结合bpftrace和perf工具进行动态分析并关注内核邮件列表中关于CFS带宽控制的最新优化如task-based throttle RFC持续跟踪该领域的技术演进。

相关文章:

Linux CFS 的 throttled_cfs_rq:被限流任务组的管理与恢复

一、简介在现代云计算和容器化环境中,CPU资源的公平分配与限制是系统稳定性的关键保障。Linux内核的CFS(Completely Fair Scheduler)带宽控制机制通过cpu.cfs_quota_us和cpu.cfs_period_us(cgroup v2中统一为cpu.max)为…...

macOS光标个性化终极指南:如何用Mousecape打造专属高效工作流

macOS光标个性化终极指南:如何用Mousecape打造专属高效工作流 【免费下载链接】Mousecape Cursor Manager for OSX 项目地址: https://gitcode.com/gh_mirrors/mo/Mousecape 在macOS的视觉交互体验中,鼠标指针作为我们与数字世界最直接的连接点&a…...

5分钟上手lilToon:打造专业级卡通角色渲染的终极指南

5分钟上手lilToon:打造专业级卡通角色渲染的终极指南 【免费下载链接】lilToon Feature-rich shaders for avatars 项目地址: https://gitcode.com/gh_mirrors/li/lilToon lilToon是一款功能强大的Unity着色器工具,专为虚拟角色和卡通渲染设计。无…...

刚考上研究生的小白怎么写综述?

除了传统的写作方法,我们需要的是一种能够将传统数周的文献调研压缩至分钟级的高效解决方案,这便是智能化科研工具的核心价值所在。 MedPeer基于国内科研现状,打造出了Deep Search这款智能文献检索与分析工具。它覆盖了3亿篇文献数据库&…...

Go语言怎么用Kafka_Go语言Kafka消息队列教程【对比】

Kafka在Go中可靠性取决于配置匹配:sarama需显式设RequiredAcksWaitForAll、Return.Successestrue及正确Version;kafka-go更简洁但兼容性弱;网络配置、advertised.listeners和认证易致生产超时。Kafka 在 Go 里不是“装个包就能用”&#xff0…...

别再为建筑高度数据发愁了!手把手教你用QGIS加载2024版全国SHP建筑轮廓(含高度字段)

2024版全国建筑轮廓数据实战:QGIS三维可视化全流程解析 城市规划师拿到最新建筑轮廓数据后,最迫切的需求往往不是数据本身,而是如何快速将其转化为可分析的视觉成果。本文将彻底解决从SHP文件加载到三维渲染的完整工作流问题,特别…...

AWVS在Ubuntu 22.04上的Docker化部署与实战配置指南

1. 为什么选择Docker部署AWVS? 如果你是一名安全工程师或者渗透测试人员,AWVS(Acunetix Web Vulnerability Scanner)应该是你工具箱里的常客。这款老牌Web漏洞扫描器以精准的SQL注入和XSS检测闻名,但传统安装方式总是…...

华为OD机试 - 符合条件的元组个数 - 递归、双指针(Java 新系统 100分)

华为OD机试 新系统 题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有…...

免费降AI率哪个好?嘎嘎降AI、比话降AI、率零实测推荐

免费降AI率哪个好?嘎嘎降AI、比话降AI、率零实测推荐 “免费降AI率到底用哪个好?”——这个问题最近被问烂了。 在各种毕业论文群里、知乎上、小红书上,到处都是这个问题。答案五花八门,有推荐这个的有推荐那个的,但大…...

HiRAG:层级知识检索增强生成,小白程序员也能轻松掌握大模型技术,速收藏!

HiRAG是一种层级知识检索增强生成框架,旨在解决现有RAG方法在处理领域特定任务时面临的语义相似实体结构距离和局部与全局知识鸿沟两大挑战。通过构建多层级知识图谱和实施三层知识检索(局部、全局、桥接),HiRAG有效增强了语义关联…...

收藏!小白也能看懂:用“天才学生”培养法揭秘大模型训练全过程

本文用“培养天才学生”的比喻,将大模型训练过程分为四个阶段:博览群书(预训练)构建知识基础,教养规矩(后训练与对齐)学习人类价值观和指令理解,独立思考(推理增强&#…...

VS2022性能剖析器实战:精准测量算法的时间与内存消耗

1. 为什么需要性能剖析工具? 写算法代码时,我们经常会遇到这样的场景:代码逻辑明明正确,但运行时间就是超出限制,或者内存消耗过大导致程序崩溃。这时候就需要性能剖析工具来帮我们找出问题所在。 我最近在准备算法竞赛…...

多仪器数字电子实验箱,数字电路实验箱,电路实验箱

数字电子实验教学系统 型号:QyDE02一、实验教学系统主要特点1.实验教学系统采用主实验箱模块化的结构组合方式设计;配有实验板安装接口底座,实验板更换简便;多模块集成,支持数字电子电路系统设计与性能验证&#xff0…...

CD-HIT安装踩坑实录:从Conda到源码编译,哪种方式最适合你的Linux服务器?

CD-HIT安装踩坑实录:从Conda到源码编译,哪种方式最适合你的Linux服务器? 生物信息学工具CD-HIT作为序列去冗余的黄金标准,几乎出现在每篇涉及高通量测序分析的论文方法部分。但当你第一次在实验室服务器上尝试安装它时&#xff0c…...

避坑指南:STM32CUBEMX串口配置常见问题及解决方案(USART/printf重定向)

STM32CubeMX串口开发实战:从原理到调试的完整避坑手册 第一次在STM32CubeMX里配置串口时,我盯着那个115200的波特率数值发呆了十分钟——这个看似简单的数字背后,隐藏着多少新手会踩的坑?从时钟树配置到DMA缓冲区,从p…...

计算机视觉需要哪些数学基础?如何高效学习线性代数和概率论?

计算机视觉需要哪些数学基础?如何高效学习线性代数和概率论? 标签:#计算机视觉、#线性代数、#人工智能、#深度学习、#自然语言处理、#神经网络、#机器学习 ### 一、痛点引入:为什么很多人怕CV数学?真相是什么&#xf…...

Java的MethodHandle与反射的性能对比

Java的MethodHandle与反射的性能对比 在Java开发中,动态调用方法是一个常见的需求,而传统的反射(Reflection)和Java 7引入的MethodHandle是两种主要实现方式。虽然反射功能强大,但因其性能开销较大,Method…...

音乐魔法解密:用Spleeter实现专业级音频分离的完整指南

音乐魔法解密:用Spleeter实现专业级音频分离的完整指南 【免费下载链接】spleeter Deezer source separation library including pretrained models. 项目地址: https://gitcode.com/gh_mirrors/sp/spleeter 你是否曾梦想过拥有"音乐魔法"&#xf…...

AI Agent工作流分布式追踪实战:OpenTelemetry从黑盒到透明化的调试方案

一、背景与挑战 在构建复杂的AI Agent工作流时,你是否遇到过这样的调试困境:一个包含数据获取、多模型推理、结果整合的流程突然失败,却无法快速定位具体卡在哪一步?日志分散在各个组件,指标只能告诉你"有错误&qu…...

2026年户外广告机市场:这五大厂家正悄然改变行业格局

当你在繁华的商圈、繁忙的交通枢纽,甚至是在社区门口,看到一块块高清亮丽的屏幕,正精准地推送着各类信息时,你是否想过,支撑这些“城市之眼”背后的技术力量正在经历一场深刻的变革?2026年的户外广告机市场…...

BP神经网络交叉验证算法与确定最佳隐含层节点数Matlab程序(直接运行、数据Excel格式、...

bp神经网络交叉验证算法和确定最佳隐含层节点个数matlab 程序,直接运行即可。 数据excel格式,注释清楚,效果清晰,一步上手。BP 神经网络交叉验证与隐含层节点自寻优工具包功能说明书一、产品定位本工具包面向“零算法背景”的实验…...

SEONIB智能排期:让站点更新从偶然事件变成系统化的增长引擎

SEONIB智能排期:让站点更新从偶然事件变成系统化的增长引擎 我记得刚开始尝试用内容获取自然流量时,最困扰我的不是写不出文章,而是写出来的文章总像一场心血来潮的烟花表演——绚烂一阵,然后沉寂。我会因为一个热点,…...

Eino - ChatTemplate 的应用

Eino - ChatTemplate 的应用 前言 在 AI 应用开发中,Prompt(提示词)是与大模型交互的核心。一个好的提示词工程能够让 AI 理解任务需求并生成高质量的回复。Eino 框架提供了强大的 ChatTemplate 功能,支持模板化管理提示词、变量…...

解密昇腾ACL事件机制:如何用Event实现多Stream精准调度(避坑指南)

昇腾ACL事件机制深度解析:多Stream协同避坑实战 当你在昇腾平台上处理8路高清视频流分析时,是否遇到过这样的困境——明明硬件算力充足,但实际吞吐量却只有理论值的60%?问题的根源往往不在算法本身,而在于对ACL事件机制…...

Labelme标注数据转YOLOv5格式:手把手教你JSON转TXT(附完整代码)

Labelme标注数据转YOLOv5格式:从原理到实践的完整指南 在计算机视觉项目中,数据标注是模型训练前的关键步骤。Labelme作为一款开源的图像标注工具,因其简单易用而广受欢迎。然而,当我们需要将Labelme生成的JSON标注文件转换为YOLO…...

LeetCode --- 2293. Min Max Game 解题报告

原问题 Question: You are given a 0-indexed integer array nums whose length is a power of 2. Apply the following algorithm on nums: Let n be the length of nums. If n == 1, end the process. Otherwise, create a new 0-indexed integer array newNums of length …...

抖音批量下载技术深度解析:从单视频到用户主页的全场景解决方案

抖音批量下载技术深度解析:从单视频到用户主页的全场景解决方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallb…...

Qwen3-ForcedAligner常见问题全解析:从错误码到成功对齐

Qwen3-ForcedAligner常见问题全解析:从错误码到成功对齐 1. 为什么你的音文对齐总是失败?先理解这个核心逻辑 想象一下这个场景:你有一段清晰的会议录音,也有完整的会议纪要文字稿,现在需要把每个字在录音里的起止时…...

Qwen3-VL-8B多模态工具亲测:上传图片就能问,本地部署真简单

Qwen3-VL-8B多模态工具亲测:上传图片就能问,本地部署真简单 1. 工具概览:你的私人视觉助手 想象一下,当你看到一张复杂的图表或一张陌生的植物照片时,只需要上传图片并提问,就能立即获得专业级的解释和分…...

Diablo Edit2:终极暗黑破坏神II存档编辑器完整指南

Diablo Edit2:终极暗黑破坏神II存档编辑器完整指南 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 还在为刷不到心仪的装备而烦恼吗?想要体验不同技能组合却不想重新练级&a…...