microsoft management c# .net windows wmi

c# - management - WMI, valor de uso de CPU negativo y Timestamp_Sys100NS en el pasado



microsoft wmi (3)

Estoy monitoreando algunas máquinas usando WMI, usando el sistema de System.Management sistemas de .NET. La consulta que estoy usando es la siguiente:

SELECT Timestamp_Sys100NS, PercentProcessorTime FROM Win32_PerfRawData_PerfOS_Processor WHERE Name=''_Total''

A partir de eso, calculo el% de uso de la CPU usando la fórmula conocida:

double cpu_usage = (1 - (double)delta_cpu / delta_time) * 100;

Funciona muy bien cada máquina menos una (hasta ahora).

El problema es que para una máquina, que es el servidor de Windows 2003 (si el hipervínculo está habilitado, si importa), a veces obtengo valores de uso de CPU negativos. En otras palabras, la expresión (double)delta_cpu / delta_time produce el número > 1 . Busqué en la web pistas sobre por qué podría estar sucediendo esto, pero no encontré nada.

¿Es este servidor de Windows 2003 específico? ¿O es un problema relacionado con el subproceso? ¿O es solo lo esperado y debería cpu_delta valor de uso de la CPU o el valor cpu_delta en algún rango?

EDITAR: La segunda cosa extraña que estoy observando con esta máquina es que el valor de Timestamp_Sys100NS no indica la fecha de FILETIME (marca desde el 1 de enero de 1600), sino que se parece a las garrapatas desde el inicio.

EDITAR 2 : Ahora he verificado que este problema se encuentra en muchos servidores Windows 2003. Y al parecer no soy el único con el mismo problema .

EDIT 3 : solucioné el problema de la marca de tiempo consultando LastBootUpTime desde Win32_OperatingSystem y agregando eso a Timestamp_Sys100NS cuando el valor de Timestamp_Sys100NS está demasiado lejos en el pasado. Eso parece dar fecha y hora correctas. El código que manipula la fecha después de que se recupera de Win32_OperatingSystem tiene este aspecto:

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

... luego ajustar a UTC ...

boot_time = boot_time.UtcDateTime;

... entonces, boot_time simplemente se agrega a la marca de tiempo ( current ) devuelta por WMI en el campo Timestamp_Sys100NS ...

if (time.Year < 2000) time = boot_time + current;

EDIT 4 : Parece que hay 3 clases de sistema con respecto a Timestamp_Sys100NS :

  1. Primero está el sistema Vista + donde el Timestamp_Sys100NS es el tiempo en tics desde la época en UTC.
  2. En segundo lugar, se encuentran algunos sistemas Windows 2003 en los que se debe agregar el Timestamp_Sys100NS a Win32_OperatingSystem.LastBootUpTime para obtener un tiempo razonable.
  3. La tercera clase son sistemas en los que hacer la adición anterior aún resulta en una fecha de días libres en la fecha y hora correctas.

EDIT 5 : Algunas de las máquinas afectadas pueden haber sido máquinas virtuales, pero no todas.



La fórmula de la que habla específicamente es PERF_100NSEC_TIMER_INV http://msdn.microsoft.com/en-us/library/ms803963.aspx

No he tratado personalmente este problema porque nunca he visto valores por debajo de cero.

Esto es todo lo que he estado haciendo:

/// <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; }

Uso:

// Calculate int cpuTime = MSPerformanceAlgorithms.CalculatePerf100NsecTimerInv( current.PercentProcessorTime, current.TimestampSys100Ns, previous.PercentProcessorTime, previous.TimestampSys100Ns);

Si veo el uso de la CPU en el administrador de tareas para el cuadro de 2003, coincide bien. Creo que puedes ignorar cualquier cosa menos que cero siempre y cuando estés calculando con estos valores.


Suena como un problema estándar de "sincronización de tiempo" para mí.

El reloj de tu sistema es ... un reloj. en su caso, su reloj puede estar funcionando rápido (tal vez se complete un minuto en el 99% de la hora real), por lo que cuando la computadora se sincronice con un reloj externo (por ejemplo, a través del servicio de hora de Windows), la hora del sistema saltará hacia atrás.

como alternativa, el usuario puede ajustar manualmente la hora del sistema (por ejemplo, el panel de control de fecha y hora), por lo que es algo que debe diseñar (¡los usuarios no estarán contentos si la hora de su sistema falla su aplicación!)

La forma en que resuelvo esto es mediante la sujeción. siempre se requieren al menos 0.0 segundos de "tiempo real" para pasar, pero también se debe fijar a un máximo de 0.5 segundos, ya que el ajuste de tiempo puede avanzar, no solo hacia atrás.

Espero que eso ayude.