Подтвердить что ты не робот

WMI, отрицательное значение использования ЦП и Timestamp_Sys100NS в прошлом

Я отслеживаю некоторые машины, использующие 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 (при включенной гиперпотоке, если это имеет значение), иногда я получаю отрицательные значения использования ЦП. Другими словами, выражение (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, чтобы получить разумное время.
  • Третий класс - это системы, в которых выполнение вышеуказанного добавления по-прежнему приводит к дате выходных дней с правильной даты и времени.

РЕДАКТИРОВАТЬ 5: Некоторые из затронутых машин, возможно, были виртуальными машинами, но не все из них.

4b9b3361

Ответ 1

это звучит как стандартная проблема синхронизации времени.

ваши системные часы - это часы. в вашем случае ваши часы могут работать быстро (возможно, это завершает минуту в 99% от фактического времени), поэтому, когда ваш компьютер синхронизируется с внешними часами (например, через службу времени Windows), ваше системное время будет отскакивать назад.

В качестве альтернативы пользователь может вручную настроить системное время (например, панель управления "Дата и время" ), поэтому вам нужно что-то разработать (ваши пользователи будут очень недовольны, если их системное время сработает ваше приложение!)

способ, которым я решаю это, - это зажим. всегда требуется не менее 0,0 секунд "реального времени" для передачи, но также зажимать максимум до 0,5 секунды, так как регулировка времени может прыгать вперед, а не только назад.

Надеюсь, что это поможет.

Ответ 2

Попробуйте использовать приложение создания кода на этом компьютере и проверьте, не получили ли вы правильные показания http://www.microsoft.com/download/en/details.aspx?id=8572

Ответ 3

Формула, о которой вы конкретно говорите, это 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 года, он соответствует штрафу. Я думаю, вы можете игнорировать все, что меньше нуля, пока вы вычисляете эти значения.