linux 休眠定时唤醒_定时器导致CPU爆满的原因

使用rust tokio Interval作为定时器,可能会在系统休眠或进程挂起恢复后,CPU爆满,甚至导致死机,Windows、iOS、Android都有这个问题。

引言

虽然rust代码写得不多,但使用C++的性能分析方法论和工具链,也能分析rust代码的性能。这次,就是通过WPT(Windows Performance Tools)和Instruments分析了rust的第三方库tokio的Interval的一个性能问题。

问题的发现

在Win10系统(CPU 12核)休眠恢复之后,发现rust进程的CPU占比超过6%,相当于1个CPU核的70%。于是,赶紧用WPT抓了一个现场。通过WPT分析,发现CPU主要被其中一个线程消耗。

5142ca59e2adf34012074375eb0861c7.png

其他平台的测试验证

由于rust代码是跨平台的SDK,因此,也需要验证下其他平台是否有同样的问题。

iOS

使用Instruments抓了iOS与Windows类似场景,消耗CPU最多的也是这个线程。

dac3a457b099b73cf67a436c68635854.png

Mac

经过反复测试,未发现Mac有这个问题。

Android

经过反复测试,未发现Android有这个问题。(后来发现,是因为Android连上电脑是充电模式,进程不会自动挂起,没有进入到可复现这个问题的路径。)

tokio的Interval的Demo实验

经过多平台的测试验证,发现Windows和iOS有这个问题,但是Mac没有发现这个问题,这就感觉到很迷糊了。通过WPT和Instruments的分析数据,已定位到相关代码,使用tokio的Interval运行一个定时任务,每隔1S执行1次。其中,tokio版本0.1.13。排查了自有代码,没有找到可能引起这个问题的代码。经过现象分析,推测可能跟tokio有关,于是,写了一个简化的Demo进行验证。

实验代码说明

创建一个循环定时器任务,每隔1S运行1次。在每次定时器任务触发时,输出以下调试信息:

  • 当前任务的序号
  • 任务触发的绝对时间
  • Instant::now()获取的时间
  • 当前任务的到期时间
pub fn test_interval() {
    
    let interval = Duration::from_millis(1000);
    let task = Interval::new_interval(interval)
        .for_each(move |deadline| {
    
            let count = {
    
                let mut count = TIME_COUNT.write().unwrap();
                *count += 1;
                *count
            };
            println!("{}, {}, now: {:?}, deadline: {:?}", count, Utc::now().format("%T"), Instant::now(), deadline);
            Ok(())
        })
        .then(|_| {
    
            Ok(())
        });
    
        MY_RUNTIME.executor().spawn(task);
}

系统休眠实验

由于Windows平台发现的问题,就是通过系统休眠的方式来发现的,因此,对Windows、Mac、Linux都进行了系统休眠实验。

实验方法:先让系统休眠一段时间(超过2分钟),然后重新激活系统,观察激活后的任务执行次数。如果系统重新激活后1S内,任务执行次数只有1-3次,属于没有问题;如果有大量任务执行,则是有问题的。

Windows系统休眠实验结果

  • 系统开始休眠时间:14:08:33。
  • 激活系统时间:14:15:05。
  • 系统激活后1S
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值