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

Как получить системное время Windows с разрешением в миллисекундах?

Как получить системное время Windows с разрешением в миллисекундах?

Если вышеуказанное невозможно, то как я могу получить время запуска операционной системы? Я хотел бы использовать это значение вместе с timeGetTime(), чтобы вычислить системное время с миллисекундным разрешением.

Спасибо заранее.

4b9b3361

Ответ 1

GetTickCount не сделает это за вас.

Посмотрите QueryPerformanceFrequency/QueryPerformanceCounter. Единственный результат здесь - это масштабирование процессора, так что сделайте свое исследование.

Ответ 3

Это выработка вышеуказанных комментариев, чтобы объяснить некоторые из них.

Во-первых, вызовы GetSystemTime * являются единственными API-интерфейсами Win32, обеспечивающими системное время. На этот раз довольно грубая гранулярность, так как большинству приложений не нужны накладные расходы, необходимые для поддержания более высокого разрешения. Время (вероятно) хранится внутри как 64-разрядное число миллисекунд. Calling timeGetTime получает 32 бита младшего порядка. Вызов GetSystemTime и т.д. Запрашивает Windows, чтобы вернуть это миллисекунду времени, после преобразования в дни и т.д. И включая время начала системы.

В машине есть два источника времени: часы процессора и встроенные часы (например, часы реального времени (RTC), программируемые интервальные таймеры (PIT) и таймер высокой точности (HPET)). Первый имеет разрешение около ~ 0,5 нс (2 ГГц), а второй, как правило, программируется до периода 1 мс (хотя более новые чипы (HPET) имеют более высокое разрешение). Windows использует эти периодические тики для выполнения определенных операций, включая обновление системного времени.

Приложения могут изменять этот период через timerBeginPeriod; однако это влияет на всю систему. ОС будет проверять/обновлять обычные события на запрошенной частоте. При низких нагрузках/частотах ЦП существуют периоды бездействия для экономии энергии. На высоких частотах нет времени, чтобы перевести процессор в состояние низкого энергопотребления. Подробнее см. Разрешение таймера. Наконец, каждый тик имеет некоторые накладные расходы и увеличение частоты потребляет больше циклов процессора.

Для более высокого разрешения время системы не поддерживается с такой точностью, не больше, чем у Биг Бен есть секундная стрелка. Использование QueryPerformanceCounter (QPC) или тиков CPU (rdtsc) может обеспечить разрешение между тиками системы. Такой подход был использован в статье журнала MSDN, которую цитировал Кевин. Хотя эти подходы могут иметь дрейф (например, из-за частотного масштабирования) и т.д., И поэтому их необходимо синхронизировать с системным временем.

Ответ 4

Начиная с Windows 8 Microsoft представила новую команду API GetSystemTimePreciseAsFileTime:

https://msdn.microsoft.com/en-us/library/windows/desktop/hh706895%28v=vs.85%29.aspx

К сожалению, вы не можете использовать это, если создаете программное обеспечение, которое также должно работать в старых операционных системах.

Мое текущее решение заключается в следующем, но помните: определенное время не точное, оно находится только рядом с реальным временем. Результат всегда должен быть меньше или равен реальному времени, но с фиксированной ошибкой (если компьютер не перешел в режим ожидания). Результат имеет миллисекундное разрешение. Для моих целей это достаточно точно.

void GetHighResolutionSystemTime(SYSTEMTIME* pst)
{
    static LARGE_INTEGER    uFrequency = { 0 };
    static LARGE_INTEGER    uInitialCount;
    static LARGE_INTEGER    uInitialTime;
    static bool             bNoHighResolution = false;

    if(!bNoHighResolution && uFrequency.QuadPart == 0)
    {
        // Initialize performance counter to system time mapping
        bNoHighResolution = !QueryPerformanceFrequency(&uFrequency);
        if(!bNoHighResolution)
        {
            FILETIME ftOld, ftInitial;

            GetSystemTimeAsFileTime(&ftOld);
            do
            {
                GetSystemTimeAsFileTime(&ftInitial);
                QueryPerformanceCounter(&uInitialCount);
            } while(ftOld.dwHighDateTime == ftInitial.dwHighDateTime && ftOld.dwLowDateTime == ftInitial.dwLowDateTime);
            uInitialTime.LowPart  = ftInitial.dwLowDateTime;
            uInitialTime.HighPart = ftInitial.dwHighDateTime;
        }
    }

    if(bNoHighResolution)
    {
        GetSystemTime(pst);
    }
    else
    {
        LARGE_INTEGER   uNow, uSystemTime;

        {
            FILETIME    ftTemp;
            GetSystemTimeAsFileTime(&ftTemp);
            uSystemTime.LowPart  = ftTemp.dwLowDateTime;
            uSystemTime.HighPart = ftTemp.dwHighDateTime;
        }
        QueryPerformanceCounter(&uNow);

        LARGE_INTEGER   uCurrentTime;
        uCurrentTime.QuadPart = uInitialTime.QuadPart + (uNow.QuadPart - uInitialCount.QuadPart) * 10000000 / uFrequency.QuadPart;

        if(uCurrentTime.QuadPart < uSystemTime.QuadPart || abs(uSystemTime.QuadPart - uCurrentTime.QuadPart) > 1000000)
        {
            // The performance counter has been frozen (e. g. after standby on laptops)
            // -> Use current system time and determine the high performance time the next time we need it
            uFrequency.QuadPart = 0;
            uCurrentTime = uSystemTime;
        }

        FILETIME ftCurrent;
        ftCurrent.dwLowDateTime  = uCurrentTime.LowPart;
        ftCurrent.dwHighDateTime = uCurrentTime.HighPart;
        FileTimeToSystemTime(&ftCurrent, pst);
    }
}

Ответ 5

GetSystemTimeAsFileTime дает лучшую точность любой функции Win32 для абсолютного времени. QPF/QPC, как предложил Джоэл Кларк, даст лучшее относительное время.

Ответ 6

В Windows база всего времени - это функция с именем GetSystemTimeAsFiletime.

  • Он возвращает структуру, которая способна удерживать время с использованием 100ns resoution.
  • Он хранится в UTC

Структура FILETIME регистрирует количество интервалов в 100 нс с 1 января 1600 года; т.е. его разрешение ограничено 100 нс.

Это формирует нашу первую функцию:

введите описание изображения здесь

64-разрядное число тиков 100ns с 1 января 1600 года несколько громоздко. Windows предоставляет удобную вспомогательную функцию, FileTimeToSystemTime, которая может декодировать это 64-разрядное целое в полезные части:

record SYSTEMTIME {
   wYear: Word;
   wMonth: Word;
   wDayOfWeek: Word;
   wDay: Word;
   wHour: Word;
   wMinute: Word;
   wSecond: Word;
   wMilliseconds: Word;
}

Обратите внимание, что SYSTEMTIME имеет встроенное ограничение разрешения 1ms

Теперь у нас есть путь от FILETIME до SYSTEMTIME:

введите описание изображения здесь

Мы могли бы написать функцию, чтобы получить текущее системное время как структуру SYSTEIMTIME:

SYSTEMTIME GetSystemTime()
{
    //Get the current system time utc in it native 100ns FILETIME structure
    FILETIME ftNow;
    GetSytemTimeAsFileTime(ref ft);

    //Decode the 100ns intervals into a 1ms resolution SYSTEMTIME for us
    SYSTEMTIME stNow;
    FileTimeToSystemTime(ref stNow);

    return stNow;
}

Кроме того, Windows уже написала для вас такую ​​функцию: GetSystemTime

введите описание изображения здесь

Локальный, а не UTC

Теперь, если вам не нужно текущее время в UTC. Что делать, если вы хотите это в свое местное время? Windows предоставляет функцию для преобразования FILETIME, которая находится в UTC в ваше местное время: FileTimeToLocalFileTime

введите описание изображения здесь

Вы можете написать функцию, которая возвращает вам FILETIME в локальное время:

FILETIME GetLocalTimeAsFileTime()
{
   FILETIME ftNow;
   GetSystemTimeAsFileTime(ref ftNow);

   //convert to local
   FILETIME ftNowLocal
   FileTimeToLocalFileTime(ftNow, ref ftNowLocal);

   return ftNowLocal;
}

введите описание изображения здесь

И скажем, вы хотите декодировать локальный FILETIME в SYSTEMTIME. Это не проблема, вы можете снова использовать FileTimeToSystemTime:

введите описание изображения здесь

К счастью, Windows уже предоставляет вам функцию, которая возвращает вам значение:

введите описание изображения здесь

Precise

Есть еще одно соображение. До Windows 8 часы имели разрешение около 15 мс. В Windows 8 они улучшили часы до 100ns (соответствующие разрешению FILETIME).

  • GetSystemTimeAsFiletime (наследие, разрешение 15 мс)
  • GetSystemTimeAsPreciseFileTime (Windows 8, разрешение 100ns)

Это означает, что мы всегда должны предпочитать новое значение:

введите описание изображения здесь

Вы запросили время

Вы просили время; но у вас есть выбор.

Часовой пояс:

  • UTC (родная система)
  • Локальный часовой пояс

Формат:

  • FILETIME (системный родной, разрешение 100ns)
  • SYTEMTIME (декодировано, разрешение 1 мс)

Резюме

  • Разрешение 100ns: FILETIME
    • UTC: GetSytemTimeAsPreciseFileTime (или GetSystemTimeAsFiletime)
    • Локальный: (сворачивайте свой собственный)
  • Разрешение 1 мс: SYSTEMTIME
    • UTC: GetSystemTime
    • Локальный: GetLocalTime

Ответ 7

QueryPerformanceCounter() создан для мелкозернистого разрешения таймера.

Это таймер с наивысшим разрешением, который система может предложить, которую вы можете использовать в коде приложения, чтобы определить узкие места производительности.

Вот простая реализация для С# devs:

    [DllImport("kernel32.dll")]
    extern static short QueryPerformanceCounter(ref long x);
    [DllImport("kernel32.dll")]
    extern static short QueryPerformanceFrequency(ref long x);
    private long m_endTime;
    private long m_startTime;
    private long m_frequency;

    public Form1()
    {
        InitializeComponent();
    }
    public void Begin()
    {
        QueryPerformanceCounter(ref m_startTime);
    }
    public void End()
    {
        QueryPerformanceCounter(ref m_endTime);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        QueryPerformanceFrequency(ref m_frequency);
        Begin();
        for (long i = 0; i < 1000; i++) ;
        End();
        MessageBox.Show((m_endTime - m_startTime).ToString());
    }

Если вы являетесь разработчиком C/С++, посмотрите здесь: http://support.microsoft.com/kb/815668

Ответ 8

Ну, этот очень старый, но есть еще одна полезная функция в библиотеке Windows C _ftime, которая возвращает структуру с локальным время как time_t, миллисекунды, часовой пояс и летнее время.