Window 任务 CPU 利用率和 Oshi CPU 利用率之间的区别
Difference between Window Task CPU Utilization and Oshi CPU usage
我使用 Oshi API (https://github.com/oshi/oshi) 来获取 CPU 用法。但是,为什么该值与任务管理器 CPU 利用率不同?我的错误是什么?
我的程序 - 平均 11.13%
任务管理器 - 平均约 29%
已编辑代码
private SystemInfo systemInformation = new SystemInfo();
private CentralProcessor proc = systemInformation.getHardware().getProcessor();
private static float[] floatArrayPercent(double d) {
float[] f = new float[1];
f[0] = (float) (100d * d);
return f;
}
private double cpuData(CentralProcessor proc) {
double d = proc.getSystemCpuLoadBetweenTicks(oldTicks);
oldTicks = proc.getSystemCpuLoadTicks();
return d;
}
@Scheduled(fixedRate = 10)
public void processProcessorInformation() {
System.out.println("The percentage of the floating value cpu: " + floatArrayPercent(cpuData(proc))[0]);
}
问题是当您打算进行 "recent" 使用计算时,您有一行代码将其重置为累积(自启动以来)使用计算。
getSystemCpuLoadBetweenTicks(oldTicks)
计算测量经过的用户、系统、空闲等。从当前计数器到您传递给它的先前计数器的滴答声,并将为您提供这些时间片之间的使用情况。在您的 cpuData()
方法中,您正确地保存了旧的刻度并且可能打算再次使用它们。那部分是正确的。
但是,在您的 processProcessorInformation()
中,您每次都将 oldTicks
数组置零:oldTicks = new long[TickType.values().length];
。因此,返回的值是自您开始以来的累计平均 CPU 使用量,而不是最后 10 秒。删除该行(或将其移到预定方法之外)应该会得到您期望的结果。
您也不需要每次都重新复制 cpu
对象。在移动 oldTicks
初始化时,您可以将该初始化移出预定方法。
在相关说明中,@Elliot-Frisch 在评论中提到涉及多个处理器的计算。在比较处理器滴答声与时间(例如,如果您正在测量经过的时间段之间的滴答声)时,这是一个有用的警告。 Ticks 在每个逻辑处理器上累积,因此您需要确保缩放 "elapsed time" 以包括每个逻辑处理器。这适用于处理每个进程 CPU 计算时,因为您只有进程可用时间作为分母,在这种情况下 Windows 任务管理器被缩放以确保没有进程超过 100%,而 * nix 结果(top
)未按比例缩放,有可能超过 100%。
但是,对于系统 CPU 的使用,我们有一个可用的 "idle" 滴答计数器,它会在所有处理器上累积滴答,并且是计算使用百分比的更好选择 -- 这就是在 getSystemCpuLoadBetweenTicks()
方法中使用,因此不需要此更正。
我使用 Oshi API (https://github.com/oshi/oshi) 来获取 CPU 用法。但是,为什么该值与任务管理器 CPU 利用率不同?我的错误是什么?
我的程序 - 平均 11.13%
任务管理器 - 平均约 29%
已编辑代码
private SystemInfo systemInformation = new SystemInfo();
private CentralProcessor proc = systemInformation.getHardware().getProcessor();
private static float[] floatArrayPercent(double d) {
float[] f = new float[1];
f[0] = (float) (100d * d);
return f;
}
private double cpuData(CentralProcessor proc) {
double d = proc.getSystemCpuLoadBetweenTicks(oldTicks);
oldTicks = proc.getSystemCpuLoadTicks();
return d;
}
@Scheduled(fixedRate = 10)
public void processProcessorInformation() {
System.out.println("The percentage of the floating value cpu: " + floatArrayPercent(cpuData(proc))[0]);
}
问题是当您打算进行 "recent" 使用计算时,您有一行代码将其重置为累积(自启动以来)使用计算。
getSystemCpuLoadBetweenTicks(oldTicks)
计算测量经过的用户、系统、空闲等。从当前计数器到您传递给它的先前计数器的滴答声,并将为您提供这些时间片之间的使用情况。在您的 cpuData()
方法中,您正确地保存了旧的刻度并且可能打算再次使用它们。那部分是正确的。
但是,在您的 processProcessorInformation()
中,您每次都将 oldTicks
数组置零:oldTicks = new long[TickType.values().length];
。因此,返回的值是自您开始以来的累计平均 CPU 使用量,而不是最后 10 秒。删除该行(或将其移到预定方法之外)应该会得到您期望的结果。
您也不需要每次都重新复制 cpu
对象。在移动 oldTicks
初始化时,您可以将该初始化移出预定方法。
在相关说明中,@Elliot-Frisch 在评论中提到涉及多个处理器的计算。在比较处理器滴答声与时间(例如,如果您正在测量经过的时间段之间的滴答声)时,这是一个有用的警告。 Ticks 在每个逻辑处理器上累积,因此您需要确保缩放 "elapsed time" 以包括每个逻辑处理器。这适用于处理每个进程 CPU 计算时,因为您只有进程可用时间作为分母,在这种情况下 Windows 任务管理器被缩放以确保没有进程超过 100%,而 * nix 结果(top
)未按比例缩放,有可能超过 100%。
但是,对于系统 CPU 的使用,我们有一个可用的 "idle" 滴答计数器,它会在所有处理器上累积滴答,并且是计算使用百分比的更好选择 -- 这就是在 getSystemCpuLoadBetweenTicks()
方法中使用,因此不需要此更正。