CPU 属性为什么不是百分比
Get-Process 显示的 CPU 是「进程自启动以来累计消耗的处理器时间(秒)」,不是瞬时占用率。它回答的是「这个进程一共干了多少活」,而不是「此刻它占多少 CPU」。要做占用率监控,必须用两次采样的差值除以时间窗口,或者直接读性能计数器。另一个容易忽略的点是分母:多核机器上单个多线程进程的占用率可以超过 100%,因为它是把所有核上的时间加在一起。
基本信息
| 适用平台 | Windows PowerShell 5.1 与 PowerShell 7(PowerShell 7 在 Linux 上该属性行为不同) |
|---|---|
| 取值口径 | CPU 为累计处理器秒数,随进程运行单调增长 |
| 占用率算法 | (本次 CPU − 上次 CPU)/ 采样间隔秒数 |
| 多核影响 | 超过 100% 说明多线程并行;除以逻辑处理器数才是整机占比 |
| 替代方式 | Get-Counter '\Process(实例名)\% Processor Time' 直接取瞬时百分比 |
| 重置条件 | 进程重启或回收后累计值归零 |
典型使用场景
- 疑似高占用确认:任务管理器显示高,用采样法核对短窗口内的真实占用
- 应用池定位:多个同名工作进程时按 PID 分别比较,找出异常实例
- 容量评估:统计一周内进程累计 CPU 时间,判断是否需要扩容
- 回归对比:发版前后相同压测场景对比累计 CPU,量化性能变化
- 卡顿分析:CPU 低但响应慢,说明瓶颈不在 CPU,转向磁盘、内存或等待
常用示例
常用示例
Get-Process -Name w3wp | Select-Object Id, CPU, WS # 先看累计值与内存
$snap = @{}
Get-Process -Name w3wp | ForEach-Object { $snap[$_.Id] = $_.CPU } # 第一次采样(按 PID 记录)
Start-Sleep -Seconds 10
Get-Process -Name w3wp | ForEach-Object {
if ($snap.ContainsKey($_.Id)) {
$pct = ($_.CPU - $snap[$_.Id]) / 10 # 除以采样间隔秒数
'{0,-8} {1,7:P1}' -f $_.Id, $pct
}
}
Get-Counter '\Process(w3wp)\% Processor Time' -SampleInterval 1 -MaxSamples 5 # 直接取瞬时百分比(多实例时实例名带 #1、#2 后缀)指标口径对照
| 指标 | 含义 | 使用注意 |
|---|---|---|
| CPU(Get-Process) | 累计处理器秒数 | 不是百分比;需两次采样求差 |
| % Processor Time | 瞬时占用百分比 | 多实例同名进程的实例名带后缀,需按 PID 对应 |
| 逻辑处理器数 | 换算整机占比的分母 | 用 Get-CimInstance Win32_ComputerSystem 的 NumberOfLogicalProcessors 查询 |
| WorkingSet(WS) | 当前物理内存占用 | 与 CPU 无关,需分别评估 |
| Private Bytes | 进程私有提交内存 | 内存泄漏排查更应看这个指标 |
对多实例进程(如多个 w3wp、多个 java)必须按 PID 对齐采样:把不同实例的 CPU 值混着相减,会得到毫无意义的负数或巨大数值。
想把占用率换算成「整机占比」,需要除以逻辑处理器数:8 核机器上一个进程采样得到 200% 的话,相当于整机约四分之一。这一点在给业务方解释时很重要。
换算与长期记录
换算与长期记录
$cores = (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors # 逻辑处理器数
'{0} 逻辑处理器' -f $cores
# 整机占比 = 采样占用率 / 逻辑处理器数
# 每 5 分钟记录一次,便于事后复盘
Get-Process -Name w3wp | Select-Object @{n='Time';e={Get-Date}}, Id, CPU, WS |
Export-Csv -Path D:\monitor\w3wp_cpu.csv -Append -Encoding UTF8 -NoTypeInformation虚拟机里 CPU 累计值正常但应用变慢,往往是宿主的 CPU 就绪延迟或超分导致的:此时要结合宿主的 CPU 就绪时间、超分比与存储延迟一起看,只看虚拟机内部指标会得出错误结论。