¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

Si lo anterior no es posible, entonces ¿cómo puedo obtener el sistema operativo hora de inicio? Me gustaría utilizar este valor junto con timeGetTime() a fin de calcular un sistema de tiempo con una resolución de milisegundos.

Gracias de antemano.

InformationsquelleAutor axilmar | 2010-09-16

10 Comentarios

  1. 7

    GetTickCount no lo harán por usted.

    Mirar en QueryPerformanceFrequency /QueryPerformanceCounter. El único problema aquí es la CPU scaling aunque, por lo que hacer su investigación.

    • QPC no es lo que quiero. Quiero que el sistema de tiempo con una precisión de milisegundos, no un temporizador.
    • Ahorro de energía (incluso de inactividad de ahorro de energía) y Turbo Boost de juego merry infierno con QPF. Solía ser muy eficaz, pero con las modernas Cpu no es bueno ya.
    • «El único problema aquí es la CPU scaling» – no es cierto. Estas funciones no trabajan con sistemas en los que la Capa de Abstracción de Hardware no ha sincronizado el TSC valores a través de núcleos/cpu: que puede ser una de varias segundo delta. Muerde cuando uno se toma la muestra en un núcleo, a continuación, en comparación con una muestra tomada en otro núcleo. Hay soluciones para multi-core de uso, pero en ninguno he visto envasadas en un públicamente disponibles de la biblioteca. Usted puede enlazar su hilo de un solo núcleo, pero a veces eso es más destructivo que el tiempo es útil.
    • GetTickCount64 será un gran trabajo.
    • QPF sólo de no funcionar correctamente en algunos de los antiguos multi core design y roto del BIOS. En general QPF funciona muy bien. Comenzando con vista especial de alta precisión de los contadores proporcionada por la placa base se utilizan para QPC
  2. 21

    Tratar en este artículo de MSDN Magazine. En realidad, es bastante complicado.

    Implementar una Continua Actualización, de Alta Resolución Proveedor de Tiempo para Windows

    • Yo no quiero un temporizador, quiero que el sistema de tiempo con una precisión de milisegundos.
    • Has leído el artículo? Que de qué se trata! Este hombre hizo exactamente lo que están pidiendo y muestra cómo se hace incluyendo el código.
    • Yo hasta votado… no puedo obtener el código en el sitio de trabajo aunque. Bloquea mi PC dura la mayor parte del tiempo. A veces funciona y cuando lo hace, es absolutamente exacto en un muy concurrido de la CPU. Todavía rummanging a través del código para ver por qué no va a funcionar. Mi set es Win7 Pro 64 bits con Visual Studio 2005 y C++ Builder XE. Me portado el código a C++ Builder si alguien está interesado. Podemos hacer un buen proyecto de código abierto 😉
    • Sería un buen proyecto de código abierto ya que este es un problema común. La mayoría de la gente no necesita la precisión extrema del código se esfuerza por lograr, pero es que estaba empaquetado y fácil de usar apuesto a que la gente podría utilizar incluso si era excesiva para ellos.
    • Por el artículo vinculado, «El código no está destinado a ser utilizado como-es en cualquier sistema disponible como problemas pueden surgir debido a…». Es de destacar que el artículo no menciona siquiera un grave problema: los contadores de rendimiento a menudo no están correctamente sincronizados a través de núcleos/cpu (Microsoft culpa a la Capa de Abstracción de Hardware (HAL)), por lo que la calibración se hace en un solo hilo no puede lear para corregir los resultados en otra. En mi mediciones en diferentes sistemas, errores de sincronización de TSC valores puede ser de varios segundos.
    • El enlace que murió por mí. web.archive.org/web/20121018065403/http://msdn.microsoft.com/…

  3. 11

    Esta es una elaboración de los comentarios anteriores para explicar algunos de los porqués.

    Primero, el GetSystemTime* llamadas son la única Api de Win32 proporcionando la hora del sistema. Este tiempo es bastante granularidad gruesa, como la mayoría de las aplicaciones no necesitan la sobrecarga necesaria para mantener una mayor resolución. El tiempo es (probablemente) que se almacenan internamente como de 64 bits recuento de milisegundos. Llamar timeGetTime obtiene el bajo para 32 bits. Llamar GetSystemTime, etc solicitudes de Windows para devolver este tiempo de milisegundos, después de la conversión en días, etc, y en particular el sistema de tiempo de inicio.

    Hay dos fuentes de tiempo en una máquina: el reloj de la CPU y de la placa de reloj (por ejemplo, reloj de tiempo real (RTC), temporizador de Intervalos Programable (PIT), y Temporizador de Eventos de Alta Precisión (HPET)). La primera tiene una resolución de alrededor de ~0.5 ns (2GHz) y la segunda es generalmente programable hasta un período de 1 ms (aunque los nuevos chips (HPET) tienen una mayor resolución). Windows utiliza estos pulsos periódicos para realizar ciertas operaciones, incluyendo la actualización de la hora del sistema.

    Aplicaciones puede cambiar este período a través de timerBeginPeriod; sin embargo, esto afecta a todo el sistema. El sistema operativo de verificación /actualización regular de los acontecimientos, con la frecuencia requerida. En condiciones de baja carga de CPU /frecuencias, existen períodos de inactividad para ahorro de energía. A altas frecuencias, no hay tiempo para poner el procesador en bajos estados de energía. Ver Resolución Del Temporizador para más detalles. Finalmente, cada pulso tiene cierta sobrecarga y el aumento de la frecuencia consume más ciclos de CPU.

    Para mayor tiempo de resolución, la hora del sistema no se mantiene a esta precisión, no más que el Big Ben tiene una segunda mano. El uso de QueryPerformanceCounter(QPC) o de la CPU garrapatas (diferencia entre rdtsc) puede proporcionar la resolución entre el sistema de tiempo de las garrapatas. Este enfoque fue utilizado en el artículo de MSDN magazine Kevin citado. A pesar de que estos enfoques pueden tener la deriva (por ejemplo, debido a la escala de frecuencia), etc y por lo tanto necesitan ser sincronizados con la hora del sistema.

    • Me gusta tu respuesta. Si su tan duro para que windows se ejecute con 1ms periodo entonces cómo puede hacer Linux es?
    • No sé cómo bien OS realiza con un período de 1ms, pero ambos pueden hacerlo. En cualquier software de diseño, concesiones que deben hacerse. Si el código diseñado para un período de 1ms o 16ms (específicamente de 15.625 ms)? Incluso entonces, algunos de los puntos de diseño se encargará de ejecutar mejor.
  4. 7

    En Windows, la base de todos los tiempos es una función llamada GetSystemTimeAsFiletime.

    • Devuelve una estructura que es capaz de aguantar un tiempo con 100 ns resoution.
    • Se mantiene en UTC

    La FILETIME estructura de los registros el número de intervalos de 100 ns desde el 1 de enero de 1600; el sentido de su resolución está limitada a 100 ns.

    Esta forma nuestra primera función:

    ¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

    De 64-bit número de 100 ns garrapatas desde el 1 de enero de 1600, es un poco difícil de manejar. Windows proporciona una útil función auxiliar, FileTimeToSystemTime que puede decodificar este entero de 64 bits en las partes útiles:

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

    Aviso que SYSTEMTIME tiene un built-en la resolución de la limitación de 1ms

    Ahora tenemos una manera de ir de FILETIME a SYSTEMTIME:

    ¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

    Podemos escribir la función para obtener la hora actual del sistema como un SYSTEIMTIME estructura:

    SYSTEMTIME GetSystemTime()
    {
        //Get the current system time utc in it's 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;
    }
    

    Excepto Windows ya escribió una función de este tipo para usted: GetSystemTime

    ¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

    Local, en lugar de UTC

    Ahora lo que si usted no desea que el tiempo actual en UTC. Lo que si lo quieres en tu hora local? Windows proporciona una función para convertir un FILETIME que está en UTC en tu hora local: FileTimeToLocalFileTime

    ¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

    Podría escribir una función que devuelve un FILETIME en local tiempo ya:

    FILETIME GetLocalTimeAsFileTime()
    {
       FILETIME ftNow;
       GetSystemTimeAsFileTime(ref ftNow);
    
       //convert to local
       FILETIME ftNowLocal
       FileTimeToLocalFileTime(ftNow, ref ftNowLocal);
    
       return ftNowLocal;
    }
    

    ¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

    Y digamos que usted desea decodificar el local FILETIME en un SYSTEMTIME. Eso no es problema, puede utilizar FileTimeToSystemTime de nuevo:

    ¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

    Afortunadamente, Windows ya que proporciona una función que devuelve el valor:

    ¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

    Precisa

    Hay otra consideración. Antes de Windows 8, el reloj tenía una resolución de alrededor de 15 ms. En Windows 8 mejora el reloj a 100 ns (que coincida con la resolución de FILETIME).

    • GetSystemTimeAsFileTime (legado, 15ms resolución)
    • GetSystemTimeAsPreciseFileTime (Windows 8, 100 ns resolución)

    Esto significa que siempre debe preferir el nuevo valor:

    ¿Cómo puedo obtener el sistema de Windows de tiempo con una resolución de milisegundos?

    Se le preguntó por el tiempo

    Se le preguntó por el tiempo; pero usted tiene algunas opciones.

    La zona horaria:

    • UTC (sistema nativo)
    • Zona horaria Local

    El formato:

    • FILETIME (sistema nativo, 100 ns resolución)
    • SYTEMTIME (decodificado, resolución de 1 ms)

    Resumen

    • 100 ns resolución: FILETIME
      • UTC: GetSytemTimeAsPreciseFileTime (o GetSystemTimeAsFileTime)
      • Local: (rollo de su propia)
    • Resolución de 1 ms: SYSTEMTIME
      • UTC: GetSystemTime
      • Local: GetLocalTime
  5. 4

    A partir de Windows 8 Microsoft ha presentado la nueva API de comandos GetSystemTimePreciseAsFileTime:

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

    Lamentablemente no se puede utilizar que si se crea un software que también se deben ejecutar en los sistemas operativos más antiguos.

    Mi solución actual es como sigue, pero ser conscientes de que El tiempo determinado no es exacta, es sólo cerca del tiempo real. El resultado debe ser siempre menor o igual que el tiempo real, pero con un límite de error (a menos que el equipo salió a la espera). El resultado tiene una resolución de milisegundos. Para mi propósito es lo suficientemente exacta.

    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);
        }
    }
    
  6. 1

    GetSystemTimeAsFileTime da la mejor precisión de cualquier función de Win32 para que el tiempo absoluto. QPF/QPC como Joel Clark sugirió dar un mejor tiempo relativo.

    • No hay nada mejor que GetSystemTimeAsFileTime? el sistema de funciones de tiempo tienen una precisión de 10 a 15 milisegundos.
    • Esa es la precisión, no de precisión. Y una llamada a timeBeginPeriod(1); se establece la precisión de 1m.
    • Ok, es la exactitud, a continuación, (yo siempre la mezcla de los dos, ya que en mi lenguaje no es sólo una palabra que representa a la vez). Hay una manera para obtener la hora del sistema en Windows con una precisión de 1 milisegundo? Estoy usando timeBeginPeriod(1), pero el tiempo es aún regresó con 10-15 exactitud de milisegundos.
  7. 0

    QueryPerformanceCounter (a) está integrado por grano fino resolución del temporizador.

    Es la más alta resolución de temporizador de que el sistema tiene para ofrecer que usted puede utilizar en el código de la aplicación para identificar cuellos de botella de rendimiento

    Aquí es una simple aplicación para C# 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());
        }
    

    Si usted es un C/C++ dev, a continuación, echar un vistazo aquí:
    http://support.microsoft.com/kb/815668

    • Desde el artículo de soporte técnico «•La llamada a la API puede fallar en algunas circunstancias. Compruebe el valor de retorno, y, a continuación, ajuste el código de la aplicación para asegurarse de que reciben los resultados sean válidos.» – sí, bueno. Estas funciones tienen muchos de los bien documentados problemas, incluyendo problemas como velocidades de CPU variar debido a los modos de ahorro de energía, y no sincronizados registros de TSC a través de núcleos.
  8. 0

    Bueno, esta es muy antigua, sin embargo, hay otra función útil en Windows de la biblioteca C de _ftime, que devuelve una estructura con la hora local como time_t, milisegundos, la zona horaria y horario de verano de la bandera.

  9. 0

    Ya que todos venimos aquí para obtener fragmentos en lugar de las aburridas explicaciones, voy a escribir uno:

    FILETIME t;
    GetSystemTimeAsFileTime(&t); //unusable as is
    
    ULARGE_INTEGER i;
    i.LowPart = t.dwLowDateTime;
    i.HighPart = t.dwHighDateTime;
    
    int64_t ticks_since_1601 = i.QuadPart; //now usable
    int64_t us_since_1601   = (i.QuadPart * 1e-1);
    int64_t ms_since_1601   = (i.QuadPart * 1e-4);
    int64_t sec_since_1601  = (i.QuadPart * 1e-7);
    
    //unix epoch
    int64_t unix_us  = (i.QuadPart * 1e-1) - 11644473600LL * 1000000;
    int64_t unix_ms  = (i.QuadPart * 1e-4) - 11644473600LL * 1000;
    double  unix_sec = (i.QuadPart * 1e-7) - 11644473600LL;
    
    //i.QuadPart is # of 100ns ticks since 1601-01-01T00:00:00Z
    //difference to Unix Epoch is 11644473600 seconds (attention to units!)
    

    Ni idea de cómo la deriva en el rendimiento del contador de respuestas subió, no hacer el deslizamiento de errores, chicos.

Dejar respuesta

Please enter your comment!
Please enter your name here