当前位置:首页>Linux>从 ARM64 定时器到 Linux hrtimer:一条完整链路

从 ARM64 定时器到 Linux hrtimer:一条完整链路

  • 2026-08-19 06:50:59
从 ARM64 定时器到 Linux hrtimer:一条完整链路

从“10ms 后叫醒我”理解 ARM64 Linux 时间系统

只跟踪一个真实问题:

一个任务请求: “我现在先睡眠,10ms 后请叫醒我。”

如果你真正理解这件事从请求到唤醒的完整路径,那么:

ARM Generic TimerclocksourceclockeventPPItickhrtimerNO_HZ

这些术语就不再是孤立名词,而是这条路径上各自负责一件具体事情的组件。


1. 现实问题:CPU 怎么知道“10ms 已经过去”?

先设想一个没有 timer 的 CPU。

程序可以执行:

for (;;);

但 CPU 本身不会天然知道:

现在过去了几毫秒;某个任务何时应该超时;某个网络包何时需要重传;某个 `sleep(10ms)` 何时结束。

最朴素的办法是让 CPU 自己不停检查:

现在到 10ms 了吗?现在到 10ms 了吗?现在到 10ms 了吗?

这叫 busy wait(忙等) 。

它的问题显而易见:

CPU 不能去运行其他任务;CPU 不能进入低功耗状态;大量电能浪费在重复检查上;多个任务有不同 deadline 时,管理会很困难。

因此,操作系统需要两种能力:

能力一:准确知道“现在是什么时刻”。能力二:提前预约“未来某个时刻,请硬件通知我”。

这两件事看似相近,实际上是不同问题。


2. 先建立直觉:秒表和闹钟

把 ARM64 的计时机制想成两个物件:

秒表:    一直走;    你随时可以问它“现在是多少”。闹钟:    你设置“在某个时刻响”;    到点后它主动提醒你。

对应到 Linux:

生活模型
Linux 术语
核心职责
秒表
clocksource
提供当前连续时间。
闹钟
clockevent
在指定 deadline 产生事件通知。

最重要的第一结论:

clocksource 是“读时间”的来源;clockevent 是“制造未来事件”的来源。

不要把它们都理解为“timer”。


3. ARM64 硬件提供了什么?

ARM Generic Timer 可以看成:

一个系统级、持续前进的计数器+每个 CPU 自己可设置的闹钟

3.1 系统计数器:硬件秒表

它以固定频率递增。

例如频率是:

62,500,000 Hz

就表示:

每秒增加 62,500,000 个计数。

可以把它想象成:

01234...

永不停地增长。

ARM64 中几个主要寄存器:

寄存器
先用白话理解
正式含义
CNTFRQ_EL0
秒表每秒跳多少格
counter frequency
CNTPCT_EL0
物理秒表当前读数
physical counter
CNTVCT_EL0
当前可见的虚拟秒表读数
virtual counter
CNTP_CVAL_EL0
物理闹钟的目标时刻
physical timer compare value
CNTV_CVAL_EL0
虚拟闹钟的目标时刻
virtual timer compare value
CNTP_CTL_EL0
 / CNTV_CTL_EL0
闹钟开关与静音开关
timer control register

此时先不必纠结 physical/virtual 的区别。只要知道:

计数器负责持续走时;比较器负责与目标时刻比较;到点后产生 timer interrupt。

4. 从“10ms 后唤醒”看硬件闹钟如何工作

假设:

当前 counter 值:1,000,000counter 频率:100MHz

那么:

10ms = 0.01 秒100,000,000 × 0.01 = 1,000,000 cycles

内核希望 10ms 后收到通知,就设置:

目标时刻 = 当前值 + 1,000,000        = 2,000,000

然后硬件会持续做这件事:

当前 counter 是否达到 2,000,000?

当达到或超过时:

timer 到期→ 发出中断请求→ CPU 被通知

这不是 CPU 在循环检查。

而是:

CPU 去运行其他任务,甚至进入 idle;硬件自己看时间;到点后硬件主动把 CPU 拉回来。

这就是 timer 的价值。


5. 第一张核心图:秒表、闹钟和中断

图1:ARM Generic Timer 从计数到中断的基本路径示意图

这张图想表达什么?

计数器    负责客观地记录时间流逝。目标时刻    由内核根据“下一件要做的事”设置。PPI    是 timer 到期后,硬件通知当前 CPU 的方式。中断    让 CPU 不必忙等。

6. 第二个现实问题:系统里不止一个“10ms 后唤醒”

真实 Linux 系统中,未来事件很多:

任务 A:10ms 后睡眠结束任务 B:12ms 后超时网络栈:15ms 后检查重传调度器:4ms 后需要时间处理驱动:20ms 后检查设备状态

但一个 CPU 通常只有一个主要的本地 Generic Timer comparator。

那怎么办?

错误的想象是:

每个软件 timer 都对应一个硬件 timer。

实际上不是。

Linux 的做法是:

把所有未来事件放进软件队列;找出最早到期的那一个;只把“最早 deadline”写进硬件闹钟。

比如:

调度器事件:4ms任务 A:10ms任务 B:12ms网络事件:15ms驱动事件:20ms

硬件 timer 只设置:

4ms 后触发。

4ms 到了,内核处理调度器事件,再重新检查:

现在最早事件是谁?

可能变成:

任务 A:还剩 6ms任务 B:还剩 8ms网络事件:还剩 11ms

于是重新设置硬件闹钟:

6ms 后触发。

7. hrtimer 的本质:软件版“未来事件调度器”

现在再引入术语:

hrtimer

它不是一块硬件,也不是一个单独 timer 寄存器。

它是 Linux 的软件机制,用于维护大量带精确 deadline 的未来事件。

你可以把它理解为:

每 CPU 一个“预约事件管理员”。职责:1. 保存很多未来事件;2. 找到最早到期的事件;3. 通知硬件闹钟只盯住最早 deadline;4. 硬件闹钟响起后,执行所有已经到期的事件;5. 再预约下一次最早 deadline。

7.1 多个软件 timer 与一个硬件 comparator 的关系

图2:多个软件定时器与硬件比较器关系结构图

为什么这个设计很重要?

因为它把:

大量软件 timer

复用到:

每 CPU 一个硬件 deadline comparator。

这是一个非常典型的操作系统设计:

软件负责复杂的多任务调度;硬件负责准确地在“最近需要处理的时刻”唤醒 CPU。

8. 回到真实例子:nanosleep(10ms) 的逻辑路径

假设用户调用:

nanosleep(10ms)

概念上,内核做的是:

1. 计算任务应在什么单调时间到期;2. 为这个任务创建一个超时事件;3. 把任务状态改为不可运行;4. 调度器切走,CPU 可运行其他任务;5. 定时器到期;6. timer interrupt 进入内核;7. 内核找到该到期事件;8. 唤醒睡眠任务;9. 调度器在合适的时机让它再次运行。

注意:

“到期” ≠ “任务瞬间运行”

到期仅意味着:

任务从“因为超时不得运行”变成“具备再次参与调度的资格”。

它真正何时获得 CPU,仍取决于:

调度器优先级CPU 是否忙抢占条件实时任务CPU affinity

这就是为什么:

sleep(10ms)

通常是:

至少睡约 10ms,但不保证恰好 10.000000ms 后在用户态继续执行。

9. 一条完整因果链

图3:定时器唤醒时序图

10. PPI 到底是什么?为什么 timer 用它?

上一节讲过 GIC 中断分类。现在结合 timer 重新理解 PPI。

PPI 的全称是:

Private Peripheral Interrupt每 CPU 私有外设中断

不要把“私有”理解成“只能有一个 CPU 使用”。

正确理解:

每一个 CPU 都有自己本地的一份 timer;每个 CPU 也有自己本地的一份 timer interrupt。

例如:

CPU 0 的最近 deadline:4ms 后CPU 1 的最近 deadline:1ms 后CPU 2 当前没有任何 deadline,进入 idleCPU 3 的最近 deadline:20ms 后

它们必须独立设置、独立到期、独立唤醒。

所以 ARM Generic Timer 使用:

每 CPU local timer→ 每 CPU PPI

而不是一个共享的 SPI。


11. 第一次引入源码:timer 从 DT 初始化

现在原理清楚后,看初始化为什么这样写。

ARM64 的时间初始化:

/* arch/arm64/kernel/time.c */void __init time_init(void){    of_clk_init(NULL);    timer_probe();    tick_setup_hrtimer_broadcast();    arch_timer_rate = arch_timer_get_rate();    if (!arch_timer_rate)        panic("Unable to initialise architected timer.\n");    lpj_fine = arch_timer_rate / HZ;    pv_time_init();}

先用白话翻译:

初始化时钟相关资源;查找并初始化系统 timer;准备 timer broadcast;确认 ARM Generic Timer 频率有效;之后系统才能可靠地处理时间和延迟。

其中:

timer_probe();

会根据 Device Tree 找到:

compatible = "arm,armv8-timer";

再调用:

arch_timer_of_init();

注册关系:

TIMER_OF_DECLARE(armv8_arch_timer,                 "arm,armv8-timer",                 arch_timer_of_init);

所以完整关系是:

DT 中 timer 节点→ compatible = arm,armv8-timer→ timer_probe()→ arch_timer_of_init()→ Linux 注册 ARM Generic Timer

12. arch_timer_of_init() 具体做什么?

源码路径:

drivers/clocksource/arm_arch_timer.c:1399

它不是简单“打开一个 timer”。

它完成几项不同职责:

static int __init arch_timer_of_init(struct device_node *np){    ...    for (...) {        irq = of_irq_get(...);        if (irq > 0)            arch_timer_ppi[i] = irq;    }    rate = arch_timer_get_cntfrq();    arch_timer_of_configure_rate(rate, np);    arch_timer_uses_ppi = arch_timer_select_ppi();    ...    ret = arch_timer_register();    return arch_timer_common_init();}

翻译成工程语言:

1. 从 Device Tree 获取 timer 对应的中断;2. 获取硬件 counter 频率;3. 决定当前 Linux 使用哪一类 timer/PPI;4. 注册每 CPU 的 timer 中断处理函数;5. 注册“读当前时间”的 clocksource;6. 注册“设置未来唤醒”的 clockevent。

这说明 ARM Generic Timer 同时被 Linux 拆成两个角色:

一部分用作时间读取;另一部分用作未来 deadline 通知。

13. counter frequency 为什么如此重要?

CNTFRQ_EL0 是计数频率。

比如:

CNTFRQ_EL0 = 100,000,000

那么:

100,000,000 次计数 = 1 秒1,000,000 次计数 = 10ms100,000 次计数 = 1ms

如果频率错了:

内核以为 1,000,000 cycles = 10ms实际硬件却让它等了 20ms

所有基于时间的机制都会错:

sleep 超时错误网络重传错误调度时间统计错误音视频定时错误NTP 校时异常性能分析时间轴错误

所以 Linux 在 ARM64 启动协议中依赖 firmware 正确设置该频率。

Device Tree 中也能写:

clock-frequency

但 Linux binding 明确认为这主要用于处理坏 firmware,不应成为正常依赖。


14. clocksource:现在终于可以准确解释它

在“10ms 后唤醒”的主线里,内核至少要知道:

当前是什么时刻?

这由 clocksource 提供。

ARM Generic Timer 注册:

static struct clocksource clocksource_counter = {    .name   = "arch_sys_counter",    .rating = 400,    .read   = arch_counter_read,    .flags  = CLOCK_SOURCE_IS_CONTINUOUS,};

其中:

static u64 arch_counter_read(struct clocksource *cs){    return arch_timer_read_counter();}

你可以把这个结构体理解为给 Linux 的一个承诺:

“如果你想知道当前连续时间,就调用我的 read();我会返回一个持续递增的计数;并告诉你该计数的频率、有效位数和可靠性。”

Linux 再把计数转换成纳秒,最终支持:

ktime_get()ktime_get_ns()CLOCK_MONOTONICCLOCK_REALTIME

14.1 读时间和设置闹钟是两条不同的路径

图4:clocksource 与 clockevent 的分工示意图

左边:

我现在几点?

右边:

未来什么时候叫我?

15. clockevent:硬件闹钟的 Linux 接口

Linux 把 ARM timer 的“设置下一次到期”能力封装为:

clockevent

它的核心字段包括:

struct clock_event_device {    void (*event_handler)(...);    int (*set_next_event)(...);    ktime_t next_event;    ...};

用人话翻译:

字段
它的含义
set_next_event
“请把硬件闹钟设置为 delta 后响”。
event_handler
“闹钟响了以后,交给谁处理”。
next_event
“当前预约的最近事件是什么时候”。
cpumask
“这块闹钟能服务哪些 CPU”。
features
“是否支持 one-shot、periodic、deep idle 等能力”。

ARM timer 初始化时:

clk->features = CLOCK_EVT_FEAT_ONESHOT;clk->name = "arch_sys_timer";clk->cpumask = cpumask_of(smp_processor_id());clk->irq = arch_timer_ppi[arch_timer_uses_ppi];clk->set_next_event = sne;

这对应的真实含义:

这个 timer 支持单次闹钟;它属于当前 CPU;它通过当前 CPU 的 timer PPI 产生中断;Linux 可调用 set_next_event 来预约下一个 deadline。

16. one-shot 到底意味着什么?

先对比两种闹钟。

16.1 周期闹钟

每隔 4ms 自动响一次。

即使系统没有任务、没有 timeout、没有网络事件,它也照样响:

4ms:响8ms:响12ms:响16ms:响...

这叫 periodic tick。

优点:

简单。

缺点:

CPU 空闲也会被反复唤醒;耗电;产生无意义中断;影响性能和延迟抖动。

16.2 单次闹钟

请在 17.3ms 后响一次;响完以后由内核决定下一次什么时候再设。

如果系统未来 1 秒内什么都不需要做:

可以不产生 250 次无意义 tick。

这叫 one-shot。

ARM Generic Timer 作为 Linux clockevent 时,关键代码:

clk->features = CLOCK_EVT_FEAT_ONESHOT;

这意味着它天然适合现代 Linux 的按需唤醒模型。


17. ARM timer 如何设置 one-shot deadline?

源码:

static __always_inline void set_next_event(        const int access,        unsigned long evt,        struct clock_event_device *clk){    unsigned long ctrl;    u64 cnt;    ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);    ctrl |= ARCH_TIMER_CTRL_ENABLE;    ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;    if (access == ARCH_TIMER_PHYS_ACCESS)        cnt = __arch_counter_get_cntpct();    else        cnt = __arch_counter_get_cntvct();    arch_timer_reg_write(access, ARCH_TIMER_REG_CVAL,                         evt + cnt, clk);    arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);}

不要被函数名和寄存器吓住,逻辑只有四步:

第一步:读取闹钟控制状态;第二步:确保闹钟已开启,确保中断未被静音;第三步:读取“现在”的 counter;第四步:写入“现在 + 等待长度”作为目标时刻。

例如:

现在:1,000,000 cycles希望:100,000 cycles 后触发写入:CVAL = 1,100,000

这就是的落地实现:

未来 deadline→ 硬件比较器

18. 到点后,IRQ 会经过哪些层?

当 counter 达到比较值:

ARM Timer 触发 PPI→ GIC→ CPU IRQ→ ARM64 exception vector→ GIC IRQ handler→ timer IRQ handler

最终到达:

timer_handler(...)

核心代码:

ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, evt);if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {    ctrl |= ARCH_TIMER_CTRL_IT_MASK;    arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, evt);    evt->event_handler(evt);    return IRQ_HANDLED;}

翻译成直观动作:

1. 确认这次 IRQ 确实是 timer 已到期;2. 暂时把闹钟静音;3. 交给 Linux 时间框架处理;4. 时间框架决定下一次什么时候再响。

18.1 为什么一定要先“静音”?

这是非常实用的硬件中断原理。

此刻:

当前 counter 已经 >= CVAL。

如果不先 mask timer interrupt:

硬件会一直认为“闹钟已到期”;CPU 可能刚处理完又立刻收到同一个 timer IRQ;形成中断风暴。

所以先静音:

timer interrupt mask = 1

然后软件处理到期事件,决定下一 deadline,最后重新设置:

新的 CVAL+ enable+ unmask

这就是一次 one-shot timer 的完整闭环。


19. event_handler 是谁?

这取决于 Linux 当前使用哪种时间策略。

早期或低精度模式下,它可能是:

tick_handle_periodic

含义:

“这是一次固定周期 tick,请更新 jiffies、进程时间统计等。”

在 high-resolution / one-shot 模式下,它通常是:

hrtimer_interrupt

含义:

“硬件闹钟响了,请检查 hrtimer 队列,执行所有已经到期的高精度事件,并重新预约下一次最近 deadline。”

因此同一个硬件 PPI:

可以先服务传统 tick;之后再服务 hrtimer 驱动的 one-shot 时间模式。

20. hrtimer IRQ 到来后实际做什么?

高精度路径入口:

void hrtimer_interrupt(struct clock_event_device *dev)

核心逻辑,先不看细节,理解它做的三件事:

1. 根据 clocksource 读取现在时间;2. 执行所有 deadline <= 当前时间的 hrtimer;3. 找到剩余 timer 中最早的 deadline,   并重新设置硬件闹钟。

源码中的对应部分:

now = hrtimer_update_base(cpu_base);__hrtimer_run_queues(cpu_base, now, flags,                     HRTIMER_ACTIVE_HARD);expires_next = hrtimer_update_next_event(cpu_base);tick_program_event(expires_next, 0);

翻译:

更新“现在”→ 跑到期队列→ 找下一次→ 重设 ARM timer

这就是整个时间系统最核心的运行循环。


21. 重新理解 hrtimer 处理流程

图5:hrtimer 中断处理流程图

这张图就是:

硬件闹钟Linux 软件 deadline 队列

之间的闭环。


22. Tick:为什么 hrtimer 已经存在,Linux 还需要 tick?

因为 Linux 不只有“用户请求 sleep”这种任务。

系统还需要周期性或逻辑周期性的工作:

推进 jiffies更新 wall time更新进程 CPU 时间统计处理调度器时间相关逻辑运行一些基于 tick 的兼容机制

传统方式是:

每 1/HZ 秒一次 timer IRQ

例如:

HZ = 250→ 每 4ms 一个 tick。

现代高精度 Linux 中,tick 经常变成:

由一个 per-CPU hrtimer 维护的“软件定期事件”。

即:

不是硬件每 4ms 固定触发;而是 hrtimer 到期后决定下一次 tick deadline,再由同一个 ARM hardware timer 唤醒。

22.1 调度 tick 也是 hrtimer

源码:

static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer){    ...    tick_sched_do_timer(ts, now);    tick_sched_handle(ts, regs);    if (unlikely(ts->tick_stopped))        return HRTIMER_NORESTART;    hrtimer_forward(timer, now, TICK_NSEC);    return HRTIMER_RESTART;}

白话解释:

这是一个“我每隔一个 tick 周期应该再做一次”的软件 timer。到期后:1. 做一次调度 tick 的工作;2. 如果当前 CPU 不需要停 tick;3. 把自己的 deadline 推到下一个周期;4. 再次加入 hrtimer 队列。

所以:

硬件 timer→ 唤醒 hrtimer 框架hrtimer 框架→ 运行 scheduler tick 这个软件定时器scheduler tick→ 再次安排自己的未来 deadline

23. 什么是 NO_HZ?先不要理解成“完全没有 tick”

假设 CPU 进入 idle,未来 500ms 内没有任何事:

没有任务需要唤醒;没有网络 timeout;没有 scheduler deadline;没有驱动定时任务。

传统 periodic tick 仍会:

每 4ms 唤醒一次 CPU。

500ms 内会产生约:

125 次无意义唤醒。

NO_HZ 的思想是:

既然没有任何事需要做,就不要每隔固定周期把 CPU 叫醒。

此时 Linux 可以停掉本 CPU 的 one-shot timer。

源码:

if (expires == KTIME_MAX) {    clockevents_switch_state(dev,                             CLOCK_EVT_STATE_ONESHOT_STOPPED);    dev->next_event = KTIME_MAX;    return 0;}

它表示:

当前没有未来 deadline,所以停止本 CPU 的硬件闹钟。

不是系统时间停止了,而是:

没有理由产生 timer interrupt。

若后来有新 deadline,例如:

100ms 后需要唤醒某任务。

Linux 再次启动 one-shot timer 并设置到 100ms 后。


24. 空闲 CPU 的真实行为

图6:空闲 CPU 的 one-shot 定时时序图

25. 一个容易忽略但很重要的问题:CPU 深度休眠时,闹钟还走吗?

如果 CPU 进入深度低功耗状态,可能有两种情况:

情况一:timer 仍然在 always-on 电源域中运行。→ deadline 到期后可以自然唤醒 CPU。情况二:该 CPU 的 local timer 也停止。→ 它自己无法在 deadline 到期时叫醒自己。

Device Tree 的:

always-on

描述 timer 是否始终有电。

Linux 中:

arch_timer_c3stop =    !of_property_read_bool(np, "always-on");

若 timer 在 deep idle 可能停止,Linux 需要:

tick broadcast

即由:

另一个仍工作的 timer或其他 CPU

负责在需要时唤醒沉睡 CPU。

这说明 NO_HZ 并不是简单的“停止 timer”:

必须同时确保不会错过 future deadline。

26. 回到启动:为什么 ARM Generic Timer 是早期初始化对象?

普通驱动通常可以晚点 probe。

但没有 timer,内核后续很多能力都不可靠:

延迟timeout调度时间维护hrtimer网络重传workqueue 延时工作profilingtimekeeping用户态 sleep

所以它走早期 Device Tree timer probe:

DT:compatible = "arm,armv8-timer"→ timer_probe()→ arch_timer_of_init()→ 注册 PPI→ 注册 clocksource→ 注册 clockevent

它和 GIC 一样属于“基础设施先行”:

GIC 提供中断传递;timer 提供时间与 deadline;普通设备和普通进程随后才能可靠运行。

27. 这一节真正应该记住的五句话

1. clocksource 是秒表:用于读取当前时间。2. clockevent 是闹钟:用于在未来 deadline 到期时触发事件。3. ARM Generic Timer 同时提供秒表和每CPU闹钟能力。4. hrtimer 是软件的 deadline 管理器:   多个软件定时器共享一个硬件比较器。5. Timer PPI 到期后,   内核处理已到期事件,并只为下一件最早事件重新设置硬件闹钟。

如果这五句清晰,那么后面读 arm_arch_timer.chrtimer.ctick-oneshot.c 时就不会迷失。


28. 读源码时应如何对应原理?

现在按“问题 → 代码”的顺序阅读。

你要回答的问题
关键源码
ARM64 timer 从哪里发现?
arch/arm64/kernel/time.c:time_init()
DT 如何匹配 ARM Generic Timer?
drivers/clocksource/timer-probe.c:timer_probe()
TIMER_OF_DECLARE()
如何取得 timer PPI 和频率?
arch_timer_of_init()
如何设置下一次硬件 deadline?
set_next_event()
timer 到期后如何进入 Linux?
timer_handler()
如何执行软件定时器?
hrtimer_interrupt()
如何选并设置下一最早 deadline?
tick_program_event()
如何在没有 future event 时停止 tick?
tick_program_event(KTIME_MAX, ...)

29. 建议先做的最小实验

不要立即上 ftrace 或 GDB。先确认“秒表”和“闹钟”都存在。

在 ARM64 QEMU Linux 中:

cat /sys/devices/system/clocksource/clocksource0/current_clocksource

常见输出:

arch_sys_counter

这就是“秒表”。

然后:

cat /sys/devices/system/clockevents/clockevent0/current_device

常见输出:

arch_sys_timer

这就是“闹钟”。

最后:

cat /proc/interrupts | grep -Ei 'arch_timer|timer'sleep 2cat /proc/interrupts | grep -Ei 'arch_timer|timer'

你会看到 timer IRQ 计数变化,这证明链路实际在工作:

硬件 timer→ PPI→ GIC→ CPU IRQ→ Linux 时间处理

30. 自测小问题

  1. 如果 Linux 只有持续递增的 counter,没有可编程 timer comparator,为什么 sleep(10ms) 仍然会很难高效实现?
  2. 如果 Linux 只有固定周期 timer interrupt,没有 clocksource,为什么无法精确知道当前时间?
  3. 为什么 Linux 不给每个软件 timeout 都分一个硬件 timer?
  4. timer 到期后,为什么 Linux 要先处理所有到期事件,再重设下一次 deadline?
  5. 为什么“10ms 到期”不等于任务恰好在 10ms 时恢复用户态运行?
  6. CPU 空闲时,为什么没有 future deadline 就应该停止 timer event,而不是继续固定 tick?
  7. timer PPI 为什么天然适合 per-CPU 的 hrtimer 和 scheduler tick?

熊树先生

持续记录 Linux 内核、嵌入式系统与底层技术学习,分享内核源码分析、驱动开发和系统软件实践。

如果你觉得今天这篇有收获,欢迎 点赞、在看、转发 三连,我们下篇见。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-08-21 13:37:22 HTTP/2.0 GET : https://f.mffb.com.cn/a/509615.html
  2. 运行时间 : 0.366571s [ 吞吐率:2.73req/s ] 内存消耗:4,863.53kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=a50da007c5d68bed03d7eb2dc2d9f486
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.001109s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001762s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000746s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000761s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001430s ]
  6. SELECT * FROM `set` [ RunTime:0.000569s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001844s ]
  8. SELECT * FROM `article` WHERE `id` = 509615 LIMIT 1 [ RunTime:0.006772s ]
  9. UPDATE `article` SET `lasttime` = 1787290643 WHERE `id` = 509615 [ RunTime:0.109361s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.012983s ]
  11. SELECT * FROM `article` WHERE `id` < 509615 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.038573s ]
  12. SELECT * FROM `article` WHERE `id` > 509615 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.016339s ]
  13. SELECT * FROM `article` WHERE `id` < 509615 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.003526s ]
  14. SELECT * FROM `article` WHERE `id` < 509615 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.006454s ]
  15. SELECT * FROM `article` WHERE `id` < 509615 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.003827s ]
0.368323s