Я наблюдаю за некоторыми машинами, используя WMI, используя .NET System.Management
. Я использую следующий запрос:
SELECT Timestamp_Sys100NS, PercentProcessorTime
FROM Win32_PerfRawData_PerfOS_Processor
WHERE Name='_Total'
Исходя из этого, я вычисляю% использования процессора по известной формуле:
double cpu_usage = (1 - (double)delta_cpu / delta_time) * 100;
Очень хорошо работает на каждой машине, кроме одной (пока).
Проблема в том, что для одной машины, которая является сервером Windows 2003 (с включенной гиперпоточностью, если это имеет значение), я иногда получаю отрицательные значения загрузки ЦП. Другими словами, выражение (double)delta_cpu / delta_time
дает число > 1
. Я искал в Интернете подсказки о том, почему это может происходить, но ничего не нашел.
Этот сервер Windows 2003 специфичен? Или это проблема, связанная с гиперпоточностью? Или это просто ожидалось, и я должен просто зафиксировать значение использования ЦП или значение cpu_delta
в некотором диапазоне?
EDIT:
Вторая странная вещь, которую я наблюдаю на этой машине, состоит в том, что значение Timestamp_Sys100NS
не указывает на FILETIME
подобную дату (тики начиная с 1 января 1600 года), а вместо этого выглядит как тики с момента загрузки.
РЕДАКТИРОВАТЬ 2 :
Теперь я проверил, что эта проблема на многих серверах Windows 2003. И я, видимо, не единственный с такой же проблемой .
РЕДАКТИРОВАТЬ 3 :
Я решил проблему с отметкой времени, запросив LastBootUpTime
из Win32_OperatingSystem
и добавив ее к Timestamp_Sys100NS
, когда значение Timestamp_Sys100NS
слишком далеко в прошлом. Это, кажется, дает правильную дату и время. Код, управляющий датой после ее получения из Win32_OperatingSystem
, выглядит следующим образом:
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
к метке времени (current
), возвращаемой WMI в поле Timestamp_Sys100NS
...
if (time.Year < 2000)
time = boot_time + current;
РЕДАКТИРОВАТЬ 4 :
Похоже, что существует 3 класса систем по отношению к Timestamp_Sys100NS
:
- Во-первых, это система Vista +, где
Timestamp_Sys100NS
- это время в тиках с эпохи в UTC.
- Во-вторых, некоторые системы Windows 2003, где
Timestamp_Sys100NS
необходимо добавить к Win32_OperatingSystem.LastBootUpTime
, чтобы получить разумное время.
- Третий класс - это системы, в которых выполнение вышеуказанного добавления все еще приводит к выходным дням правильной даты и времени.
EDIT 5 : Некоторые из затронутых машин могли быть виртуальными машинами, но не все.