我正在监视一些使用WMI的机器,使用.NET的System.Management
东西。 我正在使用的查询是这样的:
SELECT Timestamp_Sys100NS, PercentProcessorTime FROM Win32_PerfRawData_PerfOS_Processor WHERE Name='_Total'
从那我计算CPU使用率使用众所周知的公式:
double cpu_usage = (1 - (double)delta_cpu / delta_time) * 100;
它每台机器都运行得非常好,只有一台(到目前为止)。
问题是,一台机器,这是Windows 2003服务器(启用超线程,如果重要),我有时会得到负面的CPU使用率值。 换句话说, (double)delta_cpu / delta_time
expression式产生> 1
数字。 我没有searchnetworking提示为什么这可能会发生,但我什么也没find。
这个Windows 2003服务器是特定的吗? 或者是超线程相关的问题? 还是只是预期,我应该把CPU使用率值或cpu_delta
值限制在一定的范围内?
编辑:我观察与这一台机器的第二个奇怪的事情是, Timestamp_Sys100NS
值不表示像FILETIME
像date(自1600年1月1日以来的蜱),但它看起来像自引导时间以来的蜱。
编辑2 :我现在已经证实,这个问题是跨越了很多Windows 2003服务器。 而且我显然不是唯一一个有同样问题的人 。
编辑3 :我已经通过查询从Win32_OperatingSystem
LastBootUpTime
并添加到Timestamp_Sys100NS
的值Timestamp_Sys100NS
过去太远解决了时间戳问题。 这似乎给了正确的date和时间。 从Win32_OperatingSystem
检索date后的代码操作如下所示:
WbemScripting.SWbemDateTime swbem_time = new WbemScripting.SWbemDateTime(); swbem_time.Value = date_str; string time_as_file_time_str = swbem_time.GetFileTime(true); return new DateTimeOffset(epoch.Ticks + long.Parse(time_as_file_time_str), swbem_time.UTCSpecified ? TimeSpan.FromMinutes(swbem_time.UTC) : TimeSpan.Zero);
然后调整到UTC …
boot_time = boot_time.UtcDateTime;
…然后是boot_time
简单地添加到WMI在Timestamp_Sys100NS
字段中返回的时间戳( current
)…
if (time.Year < 2000) time = boot_time + current;
编辑4 :看来,有3类系统相对于Timestamp_Sys100NS
:
Timestamp_Sys100NS
是UTC以来的纪元时间。 Timestamp_Sys100NS
添加到Win32_OperatingSystem.LastBootUpTime
以获得合理的时间。 编辑5 :一些受影响的机器可能是虚拟机,但不是全部。
这听起来像是一个标准的“时间同步”问题给我。
你系统的时钟是一个时钟。 在你的情况下,你的时钟可能运行的很快(也许它会在99%的实际时间内完成一分钟),所以当你的计算机与外部时钟同步时(比如通过Windows时间服务)你的系统时间会跳回去。
或者,用户可以手动调整系统时间(例如:日期和时间控制面板),所以这是你应该设计的(如果设置系统时间让你的应用程序崩溃,你的用户会非常不高兴!
我解决这个问题的方法是夹紧。 总是需要至少0.0秒的“实时”通过,而且还要钳制到最多0.5秒,因为时间调整可能会飞跃,不仅是向后跳跃。
我希望帮助。
尝试使用该机器上的代码创建应用程序,看看你是否得到正确的读数http://www.microsoft.com/download/en/details.aspx?id=8572
您正在具体谈论的公式是PERF_100NSEC_TIMER_INV http://msdn.microsoft.com/en-us/library/ms803963.aspx
我没有亲自处理这个问题,因为我从来没有看到低于零的值。
这是我一直在做的事情:
/// <summary> /// PERF_100NSEC_TIMER_INV algorithm. /// </summary> /// <param name="n2"></param> /// <param name="d2"></param> /// <param name="n1"></param> /// <param name="d1"></param> /// <returns></returns> public static int CalculatePerf100NsecTimerInv(long n2, UInt64 d2, long n1, UInt64 d1) { int usage = 0; try { double dataDiff = (n2 - n1); double timeDiff = (d2 - d1); double dUsage = (1 - (dataDiff / timeDiff)) * 100; // Evaluate usage = (dUsage >= 0.5) ? Convert.ToInt32(Math.Ceiling(dUsage)) : 0; } catch { } // Return return usage; }
用法:
// Calculate int cpuTime = MSPerformanceAlgorithms.CalculatePerf100NsecTimerInv( current.PercentProcessorTime, current.TimestampSys100Ns, previous.PercentProcessorTime, previous.TimestampSys100Ns);
如果我观察2003盒子的任务管理器上的CPU使用情况,它可以很好地匹配。 只要你用这些数值计算,我想你可以忽略小于零的任何东西。