如何排查C++程序的CPU占用过高的问题

server/2025/3/30 11:04:00/

文章目录

  • 可能的原因
    • 程序设计的BUG
    • 系统资源问题
    • 恶意软件
    • 硬件问题
  • 通常步骤
  • 一个简单的问题代码
  • 在windows平台上如何排查
    • Windows Process Explorer
    • WinDBG
  • 在Linux平台如何排查
    • 使用TOP + GDB
    • Perf

可能的原因

程序设计的BUG

  • 有死循环
  • 低效算法与数据结构
  • 滥用自旋锁
  • 频繁的系统调用,导致用户态与内核态频繁切换

系统资源问题

  • 内存不足,系统频繁使用硬盘交换分页

恶意软件

  • 后台运行的病毒或流氓软件或自动更新的软件

硬件问题

  • 散热不良
  • 硬件老化

通常步骤

  1. 找到问题的进程
  2. 找到问题的线程
  3. 找到问题的代码位置
  4. 分析原因

一个简单的问题代码

#include <iostream>
#include <thread>
#include <vector>void busy_task() 
{while(true) {}
}void slow_algorithm() 
{for (auto i = 0L ; i < 1000000000L; ++i){volatile auto x = i * i;}
}int main()
{std::vector<std::thread> threads;threads.emplace_back(busy_task);threads.emplace_back(slow_algorithm);for(auto& t: threads){t.join();}return EXIT_SUCCESS;
}

程序以DEBUG模式编译成fst0.exe 与 fst0.pdb

在windows平台上如何排查

Windows Process Explorer

需要借助工具WindowsProcessExplorer
fst0.exe 在运行中
以管理员权限运行ProcExp,切记32 位的fst0.exe 要用32位的ProcExp,64位的fst0.exe要用64位的ProcExp
过滤出目标同时打开线程窗口
在这里插入图片描述

可以看到占用CPU过高的线程
在这里插入图片描述
我们需要设置符号文件路径
在这里插入图片描述

在这里插入图片描述
32位的程序用32位的pdb符号文件路径,64位的程序用64位的pdb符号文件路径
然后右键点击线程中的调用堆栈
在这里插入图片描述
在这里插入图片描述
可以清晰的看到程序是卡在busy_task那个函数上了!

WinDBG

怎么安装WinDbg这里就跨过,使用WinDbg时要切记,32位的程序使用32位的WinDbg调试,同时要使用32位pdb文件,64位的程序使用64位的WinDbg调试,同时要使用64位的pdb文件WinDbg最好用管理员权限打开
先行设置好符号路径与源码路径
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

现在Fst0.exe 已经在运行当中了,使用WinDbg来附加到进程,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看到这里WinDbg执行 int 3 软中断暂停了进程。

在这里插入图片描述

在Command里面执行!runaway看看各个线程的执行时间,可以看到4号线程执行时间最长
可以看看4号线程的调用堆栈
在这里插入图片描述
可以明显看到卡在了busy_task 函数,点击后面的蓝色链接可以看到源码
在这里插入图片描述

在Command里面使用qd命令退出调试

更多关于WinDBG的知识请上网自行搜索学习

在Linux平台如何排查

使用TOP + GDB

先以Debug模式编译出fst0

g++ -g fst0.cc -o fst0 -lpthread

然后运行 fst0
然后使用top
在这里插入图片描述
可以看到fst0的cpu占用很高
现在知道fst0的进程号是2473,还需要知道fst0的耗时线程是哪个
执行

top -H -p 2473

可以得到线程信息
在这里插入图片描述
可以看到有两个线程,2473主线程号与进程号相同,2474是耗时的那个子线程号
现在需要把2474那个线程的堆栈信息打印出来

sudo gdb -p 2474 -ex "thread apply all bt" -ex "detach" -ex "quit" > stack.log
cat stack.log

在这里插入图片描述
可以清楚看到程序是卡在busy_task函数,fst0.cc 文件的第8行那里。

更多gdb 相关知识自行上网学习。

Perf

perf 是Linux内核提供的性能分析工具。若你需要此工具,安装步骤如下:

# 更新软件包列表
sudo apt update# 安装与当前内核匹配的linux-tools
sudo apt install linux-tools-$(uname -r)# 验证安装
perf --version

编译程序,运行程序,打到程序PID与上面方法相同
使用perf实时查看进程热点,动态显示系统中消耗 CPU 最多的函数或进程

# 全局监控所有进程的热点
sudo perf top# 仅监控指定 PID 的进程
sudo perf top -p <PID>

例子
在这里插入图片描述
清晰的看到耗时函数是哪个


http://www.ppmy.cn/server/179656.html

相关文章

华为HCIE学习指南,如何更好的学习HCIE?

新盟教育 专注华为认证培训十余年 为你提供认证一线资讯&#xff01; 在竞争激烈的ICT行业&#xff0c;华为HCIE认证犹如一颗璀璨的明珠&#xff0c;散发着耀眼的光芒。它不仅是对个人技术能力的高度认可&#xff0c;更是开启高薪职业大门的钥匙。然而&#xff0c;华为HCIE学习…

STM32八股【3】------RAM和片上FLASH

1、RAM和FLASH构成 1.RAM ┌──────────────────────────┐ │ 栈区 (Stack) │ ← 从RAM顶端向下扩展&#xff08;存储局部变量、函数调用信息&#xff09; │--------------------------│ │ 堆区 (Heap) │ ← …

RabbitMQ 核心组件及功能详解

RabbitMQ 是一个开源的消息代理和队列服务器,其核心架构由以下关键组件构成: 一、核心组件架构 #mermaid-svg-mIHqbpvVt25Kpyl0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mIHqbpvVt25Kpyl0 .error-icon{fil…

qt QQuaternion详解

1. 概述 QQuaternion 是 Qt 中用于表示三维空间中旋转的四元数类。它包含一个标量部分和一个三维向量部分&#xff0c;可以用来表示旋转操作。四元数在计算机图形学中广泛用于平滑的旋转和插值。 2. 重要方法 默认构造函数 QQuaternion::QQuaternion(); // 构造单位四元数 (1…

Spring Boot响应压缩配置与优化

一、核心工作机制 1.1 自动协商触发条件 Spring Boot的响应压缩功能基于智能协商机制&#xff0c;需同时满足以下条件方可触发&#xff1a; 客户端支持&#xff1a;请求头包含Accept-Encoding: gzip/deflate数据量阈值&#xff1a;响应体大小超过预设值&#xff08;默认2KB&…

python每日十题(9)

外存储器的容量一般都比较大&#xff0c;而且大部分可以移动&#xff0c;便于在不同计算机之间进行信息交流。外存储器中数据被读入内存储器后&#xff0c;才能被CPU读取&#xff0c;CPU不能直接访问外存储器。本题答案为A选项。 进程是指一个具有一定独立功能的程序关于某个数…

反序列化漏洞

前提概要 本文章主要用于分享反序列化漏洞基础学习&#xff0c;以下是对反序列化漏洞的一些个人解析&#xff0c;请大家结合参考其他文章中的相关信息进行归纳和补充。 反序列化漏洞描述 反序列化漏洞是指程序在对输入的字节流进行反序列化时&#xff0c;因缺乏充分的验证和过…

Springboot body转对象时,存在多余的属性时抛异常

在Spring Boot中&#xff0c;当JSON请求体包含目标Java对象中不存在的属性时&#xff0c;默认情况下Jackson会忽略这些未知属性。若希望此时抛出异常&#xff0c;需通过配置启用Jackson的严格反序列化模式。以下是两种实现方式&#xff1a; 方法1&#xff1a;全局配置&#xf…