Window Task CPU Utilization 和 Oshi CPU 使用率之间的差异。

huangapple go评论96阅读模式
英文:

Difference between Window Task CPU Utilization and Oshi CPU usage

问题

使用 Oshi APIhttps://github.com/oshi/oshi)来获取CPU使用情况。然而,为什么该值与任务管理器的CPU利用率不同?我的错误在哪里?

*我的程序 - 平均11.13%*

[![在这里输入图片描述][1]][1]

*任务管理器 - 平均约29%*

[![在这里输入图片描述][2]][2]

*编辑后的代码*

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("浮点值CPU百分比:" + floatArrayPercent(cpuData(proc))[0]);
}

[1]: https://i.stack.imgur.com/q3fHK.jpg
[2]: https://i.stack.imgur.com/bIIAI.jpg
英文:

I using Oshi API (https://github.com/oshi/oshi) to get the CPU usage. However, why the value is different from Task Manager CPU Utilization? What is my mistake?

My Program - Average 11.13%

Window Task CPU Utilization 和 Oshi CPU 使用率之间的差异。

Task Manager - Average around 29%

Window Task CPU Utilization 和 Oshi CPU 使用率之间的差异。

Edited Code

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]);
}

答案1

得分: 1

问题在于,尽管您打算进行“最近”的使用量计算,但有一行杂乱的代码将其重置为累积(自启动以来)的使用量计算。

getSystemCpuLoadBetweenTicks(oldTicks) 计算测量了从当前计数器到您传递给它的先前计数器的已流逝的用户、系统、空闲等时钟周期,并将为您在这些时间片之间提供使用量。在您的 cpuData() 方法中,您正确地保存了旧的计数器,并且可能打算再次使用它们。那部分是正确的。

然而,在您的 processProcessorInformation() 中,您每次都将 oldTicks 数组清零:oldTicks = new long[TickType.values().length];。因此,返回的值是自启动以来的累积平均 CPU 使用率,而不是最近的 10 秒。删除该行(或将其移出计划的方法)应该能够给您带来预期的结果。

您也不需要每次都获取 cpu 对象的新副本。您可以在移动 oldTicks 初始化时,将该初始化移到计划的方法之外。

在相关说明中,@Elliot-Frisch 在评论中提到了涉及多个处理器的计算。在比较处理器时钟周期与时间(例如,如果您正在测量经过的时间周期的时钟周期),这是一个有用的警告。时钟周期在每个逻辑处理器上累积,因此您需要确保将“经过的时间”按比例缩放,以包括每个逻辑处理器。这适用于处理每个进程的 CPU 计算,因为您只能使用进程正常运行时间作为分母,在这种情况下,Windows 任务管理器被缩放以确保没有进程超过 100%,而 *nix 结果(在 top 上)没有缩放,可能会超过 100%。

然而,对于系统 CPU 使用率,我们有一个“空闲”时钟周期计数器可用,它会在所有处理器上累积时钟周期,并且是计算百分比使用率的更好选择。这也是 getSystemCpuLoadBetweenTicks() 方法中使用的内容,因此不需要进行此更正。

英文:

The problem is that while you intended to do a "recent" usage calculation, you have a stray line of code resetting it to a cumulative (since startup) usage calculation.

The getSystemCpuLoadBetweenTicks(oldTicks) calculation measures the elapsed user, system, idle, etc. ticks from the current counters to the previous ones you passed to it and will give you usage between those timeslices. In your cpuData() method you correctly save the old ticks and probably intend to use them again. That part's correct.

However, in your processProcessorInformation() you zero out the oldTicks array each time: oldTicks = new long[TickType.values().length];. And thus the value being returned is the cumulative average CPU usage since you started, rather than the last 10 seconds. Deleting that line (or moving it outside the scheduled method) should give you the results you expect.

You also don't need a fresh copy of the cpu object each time. You can move that initialization out of the scheduled method while you're moving the oldTicks initialization.

On a related note, @Elliot-Frisch mentioned in the comments about calculations involving multiple processors. This is a useful warning when comparing processor ticks vs. time (e.g., if you're measuring ticks between elapsed time periods). Ticks accumulate on every logical processor, so you would need to make sure you scale the "elapsed time" to include every logical processor as well. This applies when dealing with per-Process CPU calculations, as you only have process up time available as a denominator, and in this case Windows Task Manager is scaled to ensure no process exceeds 100%, while *nix results (on top) are not scaled and it's possible to exceed 100%.

However, for System CPU usage, we have an "idle" tick counter available, which does accumulate ticks on all the processors and is a better choice for calculating percent usage -- and is what's used in the getSystemCpuLoadBetweenTicks() method, so this correction is not required.

huangapple
  • 本文由 发表于 2020年4月9日 14:34:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/61115251.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定