乐于分享
好东西不私藏

跟着AI学Linux调度三

跟着AI学Linux调度三

人可以不挣钱,但一定要干活,今天继续学习内核调度,写文章不容易,大家点点关注

PELT 内部机制与 CPU Capacity 模型

一句话总结PELT 算法的核心是用指数衰减加权和持续维护 sched_avg 结构体中的统计字段,理解每个字段的含义(记录什么)、更新时机(何时触发)以及衰减逻辑(如何计算),是学习 PELT 算法的关键。也正是因为调度器通过统一接口(如 cpu_util_cfs()task_util())访问负载数据,上层逻辑与底层跟踪算法解耦,才使得高通 WALT 这类算法可以替换 PELT,提供不同的统计策略(如固定窗口代替指数衰减),而无需修改 EAS、schedutil 等上层逻辑。

1. 目录

PELT 内部机制
  · 11.1 pelt.c 入口函数与调用链
  · 11.2 调度事件与 sched_avg 更新
  · 11.3 运行时间的计算机制

cfs_rq→avg 聚合负载
  · 12.1 队列聚合的含义
  · 12.2 attach/detach:历史信息不丢失
  · 12.3 cfs_rq→avg 的三大用途
  · 12.4 util_avg 范围与繁忙判断

CPU Capacity 模型
  · 13.1 设备树:capacity-dmips-mhz
  · 13.2 归一化计算
  · 13.3 运行时缩放与热压力
  · 13.4 两种 capacity
  · 13.5 完整数据流
  · 13.6 实例分析:MTK DTS

PELT 时间域与跨核迁移补偿
  · 14.1 睡眠期间 se->avg 的更新行为
  · 14.2 高负载任务长时间睡眠对整体负载的影响
  · 14.3 队列等待任务的 util_avg 滞后
  · 14.4 tick 更新中 now 与 last_update_time 的归属
  · 14.5 cfs_rq_clock_pelt() 实现与三层时钟
  · 14.6 last_update_time 使用缩放时间
  · 14.7 跨核迁移时间域修正:migrate_se_pelt_lag()

PELT 内部机制

2. 11.1 pelt.c 入口函数与调用链

pelt.c 没有单一入口,按调用方分层暴露几个对外接口:


  
    
    
    
  
  bash
// 对外暴露的函数(被 fair.c 调用)
__update_load_avg_se()        ← 更新单个调度实体(task/group)的 sched_avg
__update_load_avg_cfs_rq()    ← 更新整个 cfs_rq 的 sched_avg
update_rt_rq_load_avg()       ← RT 队列
update_dl_rq_load_avg()       ← DL 队列
update_irq_load_avg()         ← IRQ 负载(schedutil 用)

2.1 CFS 路径调用链


  
    
    
    
  
  bash
fair.c: update_load_avg()           ← fair.c 封装入口,每次调度事件触发
  → __update_load_avg_se()          ← pelt.c,更新 se->avg
  → __update_load_avg_cfs_rq()      ← pelt.c,更新 cfs_rq->avg
      → ___update_load_avg()        ← 三个下划线,核心衰减计算
          → accumulate_sum()
              → decay_load()        ← 最底层:位移 + 查表

2.2 触发时机

事件 调用点
任务入队 enqueue_entity()
任务出队 dequeue_entity()
tick 更新 entity_tick()
任务迁移 migrate_task_rq_fair()
📌 注意:学习 PELT 流程,在 fair.cupdate_load_avg() 打断点是最方便的入口,而非直接进 pelt.c

3. 11.2 调度事件与 sched_avg 更新

所有事件最终都更新 struct sched_avg,每个任务(se->avg)和每个运行队列(cfs_rq->avg)各持有一份:


  
    
    
    
  
  c
struct sched_avg {
    u64           last_update_time;  // 上次更新时间戳
    u64           load_sum;          // 可运行时间衰减和(含等待队列)
    u64           runnable_sum;      // 可运行状态时间衰减和
    u32           util_sum;          // 实际在 CPU 上运行的时间衰减和
    u32           period_contrib;    // 当前周期内尚未满 1024μs 的余量
    unsigned long load_avg;          // load_sum 归一化后(乘调度权重)
    unsigned long runnable_avg;      // runnable_sum 归一化
    unsigned long util_avg;          // util_sum 归一化,[0, 1024](单任务)
};

3.1 enqueue_entity():任务入队(从睡眠唤醒)

操作对象 更新内容
se->avg 对睡眠时长做衰减:睡了多久就衰减多少;util_avg 随之降低
cfs_rq->avg attach:把 se 的贡献量加入队列聚合值

更新字段:last_update_timeutil_sum/avg(衰减后)、load_sum/avgrunnable_sum/avg

特殊逻辑:睡眠超过 160ms,util_avg 衰减至接近 0,避免"幽灵负载"拉高 cfs_rq

3.2 dequeue_entity():任务出队(进入睡眠)

操作对象 更新内容
se->avg 把本次运行时间累加util_sum,计算最新 util_avg
cfs_rq->avg detach:从队列聚合值中减去 se 的贡献量

更新字段:util_sum/avg(加入本轮运行)、load_sum/avgrunnable_sum/avg

特殊逻辑:detach 后 cfs_rq->avg 立即下降,schedutil 可能随之降频

3.3 entity_tick():周期 tick(任务正在运行)

操作对象 更新内容
se->avg 累加当前 tick 内的运行时间到 util_sum,对已过去的整周期做衰减
cfs_rq->avg 同步更新队列聚合值

更新字段:util_sum/avgperiod_contrib(周期余量)

特殊逻辑:这是 schedutil 调频的主要数据来源util_avg 稳定上升直至满载 = 1024

3.4 migrate_task_rq_fair():任务跨 CPU 迁移

阶段 操作对象 更新内容
迁出(旧 CPU) old_cfs_rq->avg detach,移除 se 贡献量
时间补偿 se->avg migrate_se_pelt_lag():补偿迁移期间的时间差,避免 util_avg 突变
迁入(新 CPU) new_cfs_rq->avg enqueue 时重新 attach

更新字段:last_update_time 被校正为新 CPU 的时钟基准

3.5 汇总对照


  
    
    
    
  
  bash
事件          se->avg 变化方向     cfs_rq->avg 变化方向
─────────────────────────────────────────────────
enqueue       衰减(睡眠惩罚)      +attach(增加)
dequeue       累加(运行贡献)      -detach(减少)
tick          累加(持续运行)      同步增加
migrate       时间补偿修正          旧-detach / 新+attach

4. 11.3 运行时间的计算机制

PELT 不用"秒表",而是懒惰更新:每次调度事件触发时,回头算"上次更新到现在经过了多久,其中任务在跑吗?"

4.1 第一步:时间差

last_update_time记录的是每次更新的时间,配合上running标志,可以判断出是休眠时间还是运行时间。


  
    
    
    
  
  bash
// pelt.c: ___update_load_sum()
delta = now - sa->last_update_time;   // 距上次更新过了多久(纳秒)
delta >>= 10;                          // 纳秒 → 1024ns 单位(≈1μs)
sa->last_update_time += delta << 10;  // 推进时间戳

now 来自 rq_clock_pelt(rq),是纳秒级单调时钟。在大小核异构系统中还会按 CPU 算力缩放,使不同核的时间可以比较。

4.2 第二步:判断任务状态


  
    
    
    
  
  bash
// pelt.c: __update_load_avg_se()
___update_load_sum(now, &se->avg,
    !!se->on_rq,             // load:     任务是否可运行(running 或 waiting)
    se_runnable(se),         // runnable: 同上(区分组调度节流状态)
    cfs_rq->curr == se);    // running:  任务是否真的在 CPU 上运行
标志 为 1 的条件 累加的字段
load 在队列中(running 或 waiting) load_sum
runnable 同上(未被 bandwidth throttle) runnable_sum
running cfs_rq->curr == se(真正占着 CPU) util_sum

4.3 第三步:把 delta 切分成周期并累加


  
    
    
    
  
  bash
delta 时间段(可能跨多个 1024μs 周期):

│◄── d1 ──►│◄── 完整周期 ──►│◄── d3 ──►│
│ 上周期余量 │  period_0  │  period_1  │ 新周期起始 │
                  ↑                          ↑
              衰减 × y¹                  权重 × y⁰

// pelt.c: accumulate_sum()
contrib = __accumulate_pelt_segments(periods, d1, d3);
sa->util_sum += running * contrib;   // running=1 才加,sleeping 时=0
sa->load_sum += load    * contrib;
sa->runnable_sum += runnable * contrib;

4.4 完整示例


  
    
    
    
  
  bash
时间轴(1格 = 1024μs):

  t0        t1        t2        t3
  │─ 运行 ─│─ 睡眠 ─│─ 运行 ─│  ← 任务状态
  └─ 上次更新 ──────────────────┘  ← t3 触发更新

t3 更新时:
  delta = t3 - t0(整段时间一次性处理)
  ├── t0~t1 段:running=1 → util_sum += 贡献 × y²  (已过2个周期,衰减)
  ├── t1~t2 段:running=0 → util_sum += 0            (睡眠,不计入)
  └── t2~t3 段:running=1 → util_sum += 贡献 × y⁰  (最近,权重最高)
🔑 关键:PELT 采用连续时间差,从 last_update_timenow 整段时间精确累计,精度是纳秒级,不受 HZ 影响。tick 采样是离散的(1ms/4ms/10ms),会漏掉 tick 之间的短暂运行;PELT 完全避开了这个问题。

cfs_rq→avg 聚合负载

5. 12.1 队列聚合的含义

cfs_rq->avg 是该 CPU 上所有可运行任务的 se->avg 的实时叠加总和


  
    
    
    
  
  bash
CPU0 的 cfs_rq:
  task_A  se->avg.util_avg = 300
  task_B  se->avg.util_avg = 200
  task_C  se->avg.util_avg = 100
  ─────────────────────────────────
  cfs_rq->avg.util_avg    = 600  ← 队列聚合值

attach / detach 就是维护这个总和的加减操作:


  
    
    
    
  
  bash
enqueue:  cfs_rq->avg += se->avg   // attach
dequeue:  cfs_rq->avg -= se->avg   // detach

好处是 O(1):任何时刻读 cfs_rq->avg 都直接拿到当前值,不需要遍历所有任务重新求和。

🔑 关键cfs_rq->avg 只统计当前可运行(runnable)的任务,睡眠任务故意不计入。睡眠任务不消耗 CPU,不应拉高当前 CPU 的繁忙程度。

6. 12.2 attach/detach:历史信息不丢失

出队减掉 se->avg,历史信息并没有丢失——它保存在 se->avg 里,通过指数衰减持续更新:


  
    
    
    
  
  bash
task_C 出队(去睡眠):
  cfs_rq->avg -= se->avg         // cfs_rq 减掉贡献
  se->avg 本身保留,util_avg=300  // 历史记录完好,继续衰减

  睡眠 32ms 后...
  se->avg.util_avg 衰减到 ~150    // PELT 指数衰减(y^32 ≈ 0.5)

task_C 入队(唤醒):
  先补算睡眠期间的衰减(decay_load)
  再 cfs_rq->avg += se->avg      // 带着衰减后的历史重新加入

PELT 的历史感知靠唤醒时带着衰减后的 util_avg 重新参与,而非"记住睡眠任务":


  
    
    
    
  
  bash
任务繁忙运行期:util_avg = 900
↓ 睡眠 32ms(一个半衰期)
util_avg 衰减到 450
↓ 唤醒,attach 到 cfs_rq->avg
→ 调度器认为这是"中等负载任务",而非新来的空任务

6.1 load_avg 与 util_avg 的区别

统计内容 用途
util_avg 实际在 CPU 上运行的时间(util_sum 归一化) schedutil 调频、EAS 选核
load_avg 可运行时间 × nice 调度权重 负载均衡(高优先级任务贡献更大)
runnable_avg 可运行时间(不含权重) 组调度内部使用

load_avg 包含 nice 权重:高优先级任务(nice=-20,权重≈88456)即使用同等 CPU 时间,对 cfs_rq->avg.load_avg 的贡献也远大于低优先级任务(nice=+19,权重≈15)。

7. 12.3 cfs_rq→avg 的三大用途

7.1 1. schedutil 调频


  
    
    
    
  
  bash
// cpufreq_schedutil.c
util     = cpu_util_cfs(rq);                        // 读 util_avg(+IRQ占用)
capacity = arch_scale_cpu_capacity(cpu);
freq     = map_util_freq(util, max_freq, capacity); // 线性映射,留 25% 余量

util_avg = 0         → 降到最低频
util_avg = capacity  → 拉到最高频
util_avg > capacity  → 已过载,钉在最高频

7.2 2. EAS 选核:find_energy_efficient_cpu()


  
    
    
    
  
  bash
// fair.c: find_energy_efficient_cpu()
// 对每个候选 CPU 计算:放入新任务后 cfs_rq->avg.util_avg 会增加多少?
// 基于 energy_model(能耗表)计算各 CPU 的能耗增量
// 选性能够用且能耗增量最小的那颗核

7.3 3. 负载均衡


  
    
    
    
  
  bash
// fair.c: sched_balance_find_src_group()
// 最忙 group 的 load_avg 超过本地 group 的 125% 才触发迁移
if (busiest_load > local_load * 125 / 100)
    → 计算 imbalance,触发 detach_tasks() + attach_tasks()

注意:负载均衡用 load_avg(含 nice 权重),而非 util_avg

7.4 调用方使用 cpu_util_cfs(),而非裸值


  
    
    
    
  
  c
// kernel/sched/sched.h
static inline unsigned long cpu_util_cfs(struct rq *rq)
{
    unsigned long util = READ_ONCE(rq->cfs.avg.util_avg);
    util += cpu_util_irq(rq);                     // 加上 IRQ 占用
    return min(util, capacity_orig_of(cpu));       // 钳位到物理上限
}

8. 12.4 util_avg 范围与繁忙判断

cfs_rq->avg.util_avg 没有上界,可以超过 1024。它是所有可运行任务的叠加,代表需求量而非实际使用量:


  
    
    
    
  
  bash
CPU0(单核,capacity=1024):
  task_A  util_avg = 700  (需要 70% CPU)
  task_B  util_avg = 600  (需要 60% CPU)
  ──────────────────────────────────────
  cfs_rq->avg.util_avg = 1300  > 1024  ← 过载,供不应求

8.1 CPU 容量:基准是 1024

不同核的容量不同,调度器用 arch_scale_cpu_capacity(cpu) 读取:

核类型 capacity_orig 说明
大核(Cortex-X4) 1024 基准,最强
中核(Cortex-A720) ≈ 590 次强
小核(Cortex-A520) ≈ 215 最省电

8.2 fits_capacity():80% 阈值


  
    
    
    
  
  c
// fair.c: EAS 选核
static bool fits_capacity(unsigned long util, unsigned long capacity)
{
    return util * 1280 < capacity * 1024;  // util < capacity × 80%
}

// 等价于:util / capacity < 0.8

小核 capacity=215
  util_avg < 172  → fits,放小核(省电)
  util_avg ≥ 172  → 不选小核,考虑中核(capacity≈590
  util_avg ≥ 472  → 不选中核,考虑大核(capacity=1024

  
    
    
    
  
  bash
util_avg 相对 capacity 的决策区间:

  0       capacity×50%  capacity×80%   capacity    capacity×N
  │───────────┼──────────────┼─────────────┼──────────────►
  │  低负载   │   中等负载   │  不放新任务  │  过载
  │  低频省电 │   线性调频   │  拉高频率   │  钉最高频+触发均衡

CPU Capacity 模型

9. 13.1 设备树:capacity-dmips-mhz

CPU capacity 的原始来源是设备树中的 capacity-dmips-mhz 属性,表示每 MHz 能跑多少 DMIPS(相对值),由芯片厂商测定:


  
    
    
    
  
  bash
/* arch/arm64/boot/dts/xxx.dtsi */
cpu@0 {
    compatible = "arm,cortex-a520";
    capacity-dmips-mhz = <382>;    /* 小核,IPC 效率较低 */
};
cpu@4 {
    compatible = "arm,cortex-a720";
    capacity-dmips-mhz = <672>;    /* 中核 */
};
cpu@7 {
    compatible = "arm,cortex-x4";
    capacity-dmips-mhz = <1024>;   /* 大核,IPC 效率最高 */
};
📌 注意capacity-dmips-mhz 只是 IPC 效率(每个时钟周期做多少工作),不是总算力。总算力还要乘以最大频率才能比较。两颗核可能 IPC 效率不同,但因为频率差异,总算力排名可能反转。

10. 13.2 归一化计算


  
    
    
    
  
  c
/* drivers/base/arch_topology.c */

// Step 1:乘最大频率,得到 raw_capacity(总吞吐量的相对值)
raw_capacity[cpu] = capacity_dmips_mhz × max_freq_MHz;

// Step 2:以所有核中最大值为基准,归一化到 1024
void topology_normalize_cpu_scale(void)
{
    u64 max_cap = max(raw_capacity[]);   // 找出最大值

    for_each_possible_cpu(cpu) {
        // SCHED_CAPACITY_SHIFT = 10,即 × 1024
        scale = (raw_capacity[cpu] << 10) / max_cap;
        topology_set_cpu_scale(cpu, scale); // 写入 per_cpu(cpu_scale)
    }
}

10.1 计算示例(骁龙 8 Gen 3)

capacity-dmips-mhz 最大频率 raw capacity_orig
Cortex-X4(大核) 1024 3300 MHz 3,379,200 1024
Cortex-A720(中核) 672 2900 MHz 1,948,800 ≈ 590
Cortex-A520(小核) 382 1860 MHz 710,520 ≈ 215

capacity_orig 存储在 per_cpu(cpu_scale, cpu),由 arch_scale_cpu_capacity(cpu) 读取。

11. 13.3 运行时缩放与热压力

CPU 降频时,实际算力等比下降;过热被限频时,额外扣减热压力:


  
    
    
    
  
  c
/* drivers/base/arch_topology.c */

// cpufreq 变频时触发通知回调
static void scale_freq_capacity(int cpu, u64 curr_freq, u64 max_freq)
{
    per_cpu(arch_freq_scale, cpu) = (curr_freq << 10) / max_freq;
}

// 合并计算最终 capacity,写入 rq
void update_cpu_capacity(unsigned int cpu)
{
    unsigned long cap = arch_scale_cpu_capacity(cpu);     // capacity_orig
    cap = cap_scale(cap, arch_scale_freq_capacity(cpu));  // × 频率比
    cap -= arch_scale_thermal_pressure(cpu);              // 减热压力
    cpu_rq(cpu)->cpu_capacity = cap;                      // 写入 rq
}

12. 13.4 两种 capacity

含义 函数 用途
capacity_orig 最高频时的算力上限(固定值) capacity_orig_of(cpu) EAS 能耗计算、cpu_util_cfs 钳位
capacity 当前频率下的实际算力(动态) capacity_of(cpu) schedutil 调频、fits_capacity 判断

  
    
    
    
  
  bash
大核满频:    capacity_orig = capacity = 1024
大核降半频:  capacity_orig = 1024,capacity = 512
大核过热限频:capacity = capacity_orig - thermal_pressure < 1024

13. 13.5 完整数据流


  
    
    
    
  
  bash
设备树 capacity-dmips-mhz
        │
        × max_freq_MHz
        │
  raw_capacity[]
        │
        ÷ max(raw_capacity) × 1024   (归一化,最强核 = 1024)
        │
  per_cpu(cpu_scale) = capacity_orig  ← arch_scale_cpu_capacity()
        │
        × (curr_freq / max_freq)      ← cpufreq 变频时更新
        │
        - thermal_pressure            ← 温控限频时扣减
        │
  cpu_rq->cpu_capacity                ← capacity_of(),调度器直接使用

14. 13.6 实例分析:MTK DTS

以下 MTK 芯片 DTS 片段中,cpu7 的 capacity-dmips-mhz(937)看似小于 cpu5/6(1024):


  
    
    
    
  
  bash
cpu5: cpu@101 {
    capacity-dmips-mhz = <1024>;
    performance-domains = <&performance 1>;  /* 中核集群 */
};
cpu6: cpu@102 {
    capacity-dmips-mhz = <1024>;
    performance-domains = <&performance 1>;  /* 中核集群 */
};
cpu7: cpu@200 {
    capacity-dmips-mhz = <937>;
    performance-domains = <&performance 2>;  /* 大核集群(独立) */
};

14.1 为什么 cpu7 是大核却 capacity-dmips-mhz 更小?

capacity-dmips-mhz 只是 IPC 效率(每 MHz 的工作量),大核(X 系列)的设计取向是堆频率换性能

特性 中核 A720(cpu5/6) 大核 X 系列(cpu7)
IPC 效率 / MHz 高(1024) 稍低(937)
最大频率 较低(~2.6 GHz) 较高(~3.2 GHz)
流水线宽度 较窄 更宽(更多执行单元)
单线程绝对性能 中等 最高

代入归一化公式(假设 cpu5/6 max_freq=2600 MHz,cpu7 max_freq=3200 MHz):


  
    
    
    
  
  bash
cpu5/6:raw = 1024 × 2600 = 2,662,400
cpu7:  raw =  937 × 3200 = 2,995,200  ← 更高(频率优势弥补了 IPC 差距)

归一化后(以最大值为基准):
cpu7:   2995200 / 2995200 × 1024 = 1024   ← 最终是最强核
cpu5/6: 2662400 / 2995200 × 1024 ≈  910
🔑 关键capacity-dmips-mhz 是内核计算的中间输入,不能直接比大小。调度器使用的是归一化后的 capacity_orig(= DMIPS/MHz × max_freq,再归一化)。cpu7 虽然每 MHz 效率低,但更高的最大频率让它最终成为算力最强的核,capacity_orig = 1024

PELT 时间域与跨核迁移补偿

15. 14.1 睡眠期间 se->avg 的更新行为

任务睡眠期间,se->avg 完全不会被更新——这是 PELT 刻意设计的懒惰求值,不是缺陷。

update_load_avg() 只在以下调度事件触发,睡眠中的任务不会触发任何一条:


  
    
    
    
  
  bash
enqueue_entity()    ← 进队列时
set_next_entity()   ← 被选中即将运行时
put_prev_entity()   ← 被抢占下来时
dequeue_entity()    ← 离开队列时

唤醒时,enqueue_entity() 调用 update_load_avg(),对整段睡眠时间做一次性补算


  
    
    
    
  
  c
// 任务睡了 500ms 后唤醒:
delta = now - last_update_time ≈ 500ms → n ≈ 488 个周期
running = 0(睡眠期间不在 CPU 上)

decay_load() 处理大 n 的快速路径:
static u64 decay_load(u64 val, u64 n)
{
    if (n >= LOAD_AVG_PERIOD * 63)  // n >= 2016 周期 ≈ 2 秒
        return 0;                    // 直接清零,O(1)

    val >>= n / LOAD_AVG_PERIOD;    // 每 32 周期右移一次(×0.5)
    n   %= LOAD_AVG_PERIOD;
    return (val * runnable_avg_yN_inv[n]) >> 32;  // 余数查表
}
睡眠时长 处理方式 util_avg 结果
< 32ms 查表修正 衰减不多,仍有历史
32ms 右移 1 位 减半
~160ms(5 个半衰期) 右移 5 次 + 查表 < 3%,接近消失
≥ 2 秒 直接 return 0 归零,O(1)

16. 14.2 高负载任务长时间睡眠对整体负载的影响

cfs_rq->avg 在任务出队(进入睡眠)时立即下降,而非等待 PELT 慢慢衰减:


  
    
    
    
  
  bash
dequeue_entity():
    update_load_avg(cfs_rq, se, 0)       // 先算清最后一段运行时间
    detach_entity_load_avg(cfs_rq, se)   // 立即从队列中减去贡献
        → cfs_rq->avg -= se->avg         // ← 这一刻负载就降了

  
    
    
    
  
  bash
多个高负载任务同时睡眠:
  task_A util_avg=700 → detach → cfs_rq -= 700
  task_B util_avg=600 → detach → cfs_rq -= 600
  task_C util_avg=300 → detach → cfs_rq -= 300

  睡前:cfs_rq->avg.util_avg = 1600(过载)
  全部睡后:cfs_rq->avg.util_avg = 0   ← 立即降到 0
  → schedutil 立即降频,EAS 认为 CPU 空闲
数据 睡眠期间 说明
cfs_rq->avg 立即下降(detach 时减去) 只统计当前可运行任务
se->avg 冻结,不更新,唤醒时一次性衰减 保留任务历史,供唤醒时选核参考
🔑 关键:PELT 的衰减保护的是任务级别的历史(se->avg),整体 CPU 负载(cfs_rq->avg)始终只反映当前可运行任务,任务一睡就立刻摘除,不存在"幽灵负载拉高 cfs_rq"的问题。

17. 14.3 队列等待任务的 util_avg 滞后

任务在队列中等待(runnable 但没在运行)时,se->avg 只在被调度事件触碰时才更新。如果因优先级低、竞争激烈而长时间未被调度,se->avg 就会冻结在上次更新的值。

cfs_rq->avg 不受影响,每个 tick 通过 entity_tick() → __update_load_avg_cfs_rq() 持续更新,使用的是 cfs_rq 级别的状态(load.weighth_nr_runningcurr != NULL),不依赖各个 se 是否最近被更新。


  
    
    
    
  
  bash
now = T(当前时刻)

curr->avg.last_update_time      = T - 4ms    ← 每 tick 更新,非常新鲜
waiting_task->avg.last_update_time = T - 5分钟  ← 上次运行时设置,非常陈旧
cfs_rq->avg.last_update_time    = T - 4ms    ← 每 tick 更新,非常新鲜

等待任务最终被 set_next_entity() 选中时,update_load_avg() 对全部等待时间做一次性补算,running=0,大 delta 经 decay_load() 衰减到接近 0。

18. 14.4 tick 更新中 now 与 last_update_time 的归属

update_load_avg() 进入时取一次时间快照,secfs_rq 用同一个 now,但各自用自己的 last_update_time 计算 delta:


  
    
    
    
  
  c
// kernel/sched/fair.c
static inline void update_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
{
    u64 now = cfs_rq_clock_pelt(cfs_rq);   // ← 统一快照

    __update_load_avg_se(now, cfs_rq, se);       // delta = now - se->avg.last_update_time
    update_cfs_rq_load_avg(now, cfs_rq);         // delta = now - cfs_rq->avg.last_update_time
}

// ___update_load_sum() 内部(se 和 cfs_rq 都走这里)
delta = now - sa->last_update_time;    // sa 是 &se->avg 或 &cfs_rq->avg
delta >>= 10;
sa->last_update_time += delta << 10;   // 各自推进自己的时间戳

19. 14.5 cfs_rq_clock_pelt() 实现与三层时钟


  
    
    
    
  
  c
// kernel/sched/fair.c
static inline u64 cfs_rq_clock_pelt(struct cfs_rq *cfs_rq)
{
    if (unlikely(cfs_rq->removed.nr))
        update_removed_cfs_rq(cfs_rq);   // 组调度移除修正

    return rq_clock_pelt(rq_of(cfs_rq)) - cfs_rq->removed.runnable_sum;
}

// kernel/sched/sched.h
static inline u64 rq_clock_pelt(struct rq *rq)
{
    return rq->clock_pelt - rq->lost_idle_time;  // 去掉空闲时间
}

rq->clock_peltupdate_rq_clock_pelt() 推进,按 CPU 算力缩放


  
    
    
    
  
  c
// kernel/sched/pelt.c
static inline void update_rq_clock_pelt(struct rq *rq, s64 delta)
{
    if (unlikely(is_idle_task(rq->curr))) {
        _update_idle_rq_clock_pelt(rq);   // 空闲:clock_pelt 不推进
        return;
    }
    // cap_scale(v, s) = v * s >> 10 = v * s / 1024
    rq->clock_pelt += cap_scale(delta, arch_scale_cpu_capacity(cpu_of(rq)));
}

大核(capacity=1024):clock_pelt += delta × 1024/1024 = delta   (全速)
中核(capacity=590) :clock_pelt += delta × 590/1024  ≈ 0.58×delta
小核(capacity=215) :clock_pelt += delta × 215/1024  ≈ 0.21×delta

19.1 完整调用链


  
    
    
    
  
  bash
scheduler_tick()
  → update_rq_clock(rq)                  // core.c
      delta = sched_clock_cpu() - rq->clock
      rq->clock += delta
      → update_rq_clock_task(rq, delta)
          rq->clock_task += delta
          → update_rq_clock_pelt(rq, delta)
              if idle: lost_idle_time 增加,clock_pelt 不动
              else:    rq->clock_pelt += delta × capacity / 1024

19.2 三个时钟的关系

时钟 含义 特点
rq->clock 原始单调时钟(纳秒) 无论何种状态都推进
rq->clock_task 去掉 IRQ/steal 的任务时钟 排除中断占用
rq->clock_pelt 按算力缩放,空闲暂停 PELT 使用,跨核可比

20. 14.6 last_update_time 使用缩放时间

last_update_time 存储的是 PELT 缩放时间,与 now 完全同一时间域。now 来自 cfs_rq_clock_pelt()(已缩放),last_update_time 每次更新都从同一个 now 写入:


  
    
    
    
  
  bash
sa->last_update_time += delta << 10;   // 存回缩放纳秒,与 now 同单位

last_update_time 本质上不是"几点几分",而是**“截至上次更新,这颗核累计做了多少等价工作量”**,和物理时间是不同的尺度。这保证了 delta = now - last_update_time 在同一颗 CPU 上始终正确。

21. 14.7 跨核迁移时间域修正:migrate_se_pelt_lag()

21.1 问题根源


  
    
    
    
  
  bash
大核(capacity=1024):1ms 真实时间 → clock_pelt += 1.000ms
小核(capacity=215) :1ms 真实时间 → clock_pelt += 0.210ms

任务在大核最后更新时:last_update_time = 1000(大核时间域)
迁移到小核,小核当前:clock_pelt = 210(小核时间域)
直接相减:delta = 210 - 1000 = -790  ← 负数,错误

21.2 修正公式


  
    
    
    
  
  bash
// 旧核上,从上次更新到迁移时刻的 lag(旧核时间域)
lag_old = now_old_pelt - se->avg.last_update_time

// 换算成真实时间(纳秒)
lag_real = lag_old * 1024 / capacity_old

// 换算成新核时间域
lag_new = lag_real * capacity_new / 1024
        = lag_old * capacity_new / capacity_old   ← 直接按算力比缩放

// 设置修正后的 last_update_time
se->avg.last_update_time = now_new_pelt - lag_new

21.3 完整迁移流程


  
    
    
    
  
  bash
migrate_task_rq_fair(p, new_cpu)          ← 在旧核上执行
    │
    ├─ update_load_avg()                   // 算清旧核上最后一段运行时间
    │      se->avg.last_update_time = now_old
    │
    ├─ detach_entity_load_avg()            // 从旧核 cfs_rq->avg 减去贡献
    │
    └─ migrate_se_pelt_lag(se)            // 修正时间域
           lag_old = now_old - lut_old
           lag_new = lag_old × capacity_new / capacity_old
           se->avg.last_update_time = now_new - lag_new

enqueue_entity() 在新核执行:
    delta = now_new - (now_new - lag_new) = lag_new   ← 正确
    running = 0(迁移期间不在任何 CPU 上)
    → util_sum 按 lag_new 衰减,不累加运行时间

21.4 数值示例


  
    
    
    
  
  bash
大核(capacity=1024)运行任务:
  last_update_time = 5000(大核时间)
  迁移时 now_old   = 5100
  lag_old = 100

迁移到小核(capacity=215):
  lag_new = 100 × 215 / 1024 ≈ 21(小核时间)
  小核当前 now_new = 1050(小核时间)
  → se->avg.last_update_time = 1050 - 21 = 1029

小核 enqueue 时:
  delta = 1050 - 1029 = 21   ← 正确,不会突变
🔑 关键last_update_time 是 PELT 缩放时间域的时间戳,不同核的时间域不通用。跨核迁移必须按算力比(capacity_new / capacity_old)折算 lag,否则迁移后首次更新的 delta 会严重失真。
基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-05-09 17:06:22 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/594355.html
  2. 运行时间 : 0.103201s [ 吞吐率:9.69req/s ] 内存消耗:4,830.77kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=89fea98b3176b599409c2d21890c2cd9
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000417s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000566s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000270s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000329s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000485s ]
  6. SELECT * FROM `set` [ RunTime:0.000207s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000663s ]
  8. SELECT * FROM `article` WHERE `id` = 594355 LIMIT 1 [ RunTime:0.000468s ]
  9. UPDATE `article` SET `lasttime` = 1778317582 WHERE `id` = 594355 [ RunTime:0.003913s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000354s ]
  11. SELECT * FROM `article` WHERE `id` < 594355 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000517s ]
  12. SELECT * FROM `article` WHERE `id` > 594355 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000376s ]
  13. SELECT * FROM `article` WHERE `id` < 594355 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000865s ]
  14. SELECT * FROM `article` WHERE `id` < 594355 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.009297s ]
  15. SELECT * FROM `article` WHERE `id` < 594355 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.011168s ]
0.104983s