编程之美——CPU占用率曲线

本文详细解读了在阅读《编程之美》时遇到的一个疑惑:为什么在双核操作系统中运行死循环时,CPU占用率并非100%。通过分析操作系统对进程的调度策略,提出将进程限定在一个核上运行的方法来验证理论。同时,讨论了书中提供的正弦曲线代码清单在实际操作中的表现,并提供了调整方法。

前几天终于买了本《编程之美》,从第一题开始做,争取在找工作之前尽快看完。其实这本书看起来很难,但是弄明白思考的方式,问题就变得很简单了。
第一题是CPU占用率曲线的问题,这个题在之前已经写过了,可以参考Windows控制CPU使用率曲线,这篇文章也写了linux下的实现,大家可以参考。
说一下对《编程之美》 1.1的一点注释吧。
1. 如果我们写一个死循环,while(1); ,对于双核的操作系统,并不会导致CPU的使用率为100%,在作者的电脑上,用任务管理器观察是稳定在50%。
2. 对于双核的操作系统(目前都有四核了),使用书上提供的正弦曲线代码清单,出现的也不是规则的正弦曲线。
对于新书来说,这是足以困扰我们,打击新手信心的一件事。为什么会这样呢?
这是由于操作系统对进程的调度,操作系统会把此进程安排在两个核去执行,导致在任务管理器上看到的不标准。因此,笔者建议,大家在自己电脑上实验书中提供的代码时,最好把进程放在一个核去运行。很简单,只需要#include <windows.h>,并且在main()函数里加上SetThreadAffinityMask(GetCurrentThread(), 1);就可以了。注意1代表是哪一个核,试试就知道了~

<think>嗯,用户正在询问如何排查和解决CPU占用率高的问。这确实是一个常见的系统性能问。用户可能是一位开发者或运维人员,遇到了服务器性能瓶颈,或者正在准备面试——因为引用[1]提到面试官问过这个问。 从用户提供的引用材料来看,ta已经做了一些基础调研,但需要更系统的排查方法。引用[1]提到Linux系统的排查经验,引用[2]给出Java进程的具体操作步骤,引用[3]则展示了一个线程死循环的代码案例。这些材料质量参差不齐,需要整合成逻辑清晰的排查流程。 用户的核心诉求是"如何排查和解决",因此回复需要突出可操作性。应该从宏观到微观设计排查路径:先定位进程,再定位线程,最后分析代码。每个步骤都要给出具体命令和解读方法,比如top命令的交互操作(引用[2]提到的Shift+</>切换高亮列很实用)。 特别要注意几个技术细节:1) Java进程需要用jstack配合线程ID转换(十六进制转换容易出错);2) 死循环和死锁的表现差异(CPU高 vs 等待);3) 容器化环境(如Docker)的排查差异。用户没提环境细节,所以需要涵盖通用场景。 解决方案部分要区分应急处理和根治措施。像引用[3]的线程睡眠方案只能算临时规避,更优解应该是用ScheduledExecutorService。对于算法优化,可以举斐波那契数列的例子说明递归优化空间。 最后考虑补充两个实用技巧:1) perf工具做CPU火焰图定位热点函数 2) 用cgroups限制进程资源。虽然这些进阶内容可能超出用户当前需求,但对高阶用户有价值。 准备在相关问里埋个伏笔——如果用户后续追问,可以展开讲解异步编程优化或容器诊断方案。现在先把回复结构拆解成诊断流程、解决方案、预防措施三部分,确保每个命令都有示例输出和解读逻辑。</think>排查CPU占用率高问需要系统化诊断,以下是详细步骤和解决方案: --- ### 🔍 一、诊断流程(Linux系统) #### 1. **定位高CPU进程** ```bash top # 实时查看进程资源占用 ``` - **操作技巧**: - 按 `1`:显示所有CPU核心的独立使用率 - 按 `Shift + P`:按CPU占用排序 - 按 `c`:显示进程完整命令 - 记录高CPU进程的 **PID**(如Java进程PID为1234) #### 2. **分析进程内线程** ```bash top -H -p 1234 # 查看指定进程的所有线程 ``` - 记录高CPU线程的 **十六进制PID**(如线程PID 5678 的十六进制为 `0x162E`) #### 3. **线程堆栈分析(Java示例)** ```bash jstack 1234 > thread_dump.txt # 生成线程快照 ``` - 在 `thread_dump.txt` 中搜索 `nid=0x162E`(对应线程PID 5678),定位线程堆栈 #### 4. **检查系统调用** ```bash perf top -p 1234 # 实时监控进程系统调用 strace -p 5678 -c # 统计线程系统调用(替换5678为实际线程PID) ``` - 关注频繁调用的系统函数(如文件读写、网络请求) #### 5. **辅助工具** - **火焰图**:可视化CPU时间消耗 ```bash perf record -F 99 -p 1234 -g -- sleep 30 perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flame.svg ``` - **监控工具**:`vmstat 1`(查看上下文切换)、`pidstat -t -p 1234 1`(线程级监控) --- ### 🛠️ 二、常见原因与解决方案 | **问类型** | **典型表现** | **解决方案** | |---------------------|----------------------------|---------------------------------------| | **死循环** | 线程持续占用CPU(如引用[3])| 检查循环退出条件,添加`Thread.sleep()` | | **锁竞争** | 大量线程处于`BLOCKED`状态 | 优化锁粒度,改用并发集合类 | | **算法低效** | 递归或复杂计算占用CPU | 优化算法(如缓存中间结果) | | **频繁GC** | `gc.log`显示Full GC频繁 | 调整JVM参数,分析内存泄漏 | | **IO阻塞** | 高`iowait`(`top`可见) | 优化磁盘读写,使用异步IO | | **第三方库缺陷** | 特定库版本线程异常 | 升级依赖库或替换实现 | --- ### 🛡️ 三、预防措施 1. **代码层面**: - 避免在循环中同步阻塞操作 - 使用线程池控制并发量 - 复杂计算添加超时中断机制 2. **监控层面**: ```bash # 定期记录资源使用 crontab -e */5 * * * * pidstat -u -p ALL 1 60 > /monitor/cpu_$(date +\%F).log ``` 3. **压测验证**: - 使用JMeter/Siege模拟高并发场景 - 对比优化前后的CPU使用率曲线 > 💡 **关键提示**:容器环境(如Docker)需在宿主机执行 `top` 或 `perf` 时添加 `--cap-add SYS_ADMIN` 权限[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值