2009-11-04 11 views
15

Estoy escribiendo una clase Socket portátil que admite tiempos de espera para enviar y recibir ... Para implementar estos tiempos de espera estoy usando select() .... Pero, a veces necesito saber cuánto tiempo estuve bloqueado dentro de select() cuál de por supuesto en Linux me gustaría poner en práctica llamando gettimeofday() antes y después llamo select() y luego usando timersub() para calcular el delta ...¿Qué debo usar para reemplazar gettimeofday() en Windows?

Teniendo en cuenta que en Windows select()struct timeval acepta por su tiempo de espera, ¿qué método debería utilizar para sustituir gettimeofday () en Windows?

Respuesta

18

acabé encontrando esta página: gettimeofday() en las ventanas [editar: Enlace eliminado debido ahora apunta a un sitio de publicidad]. Que tiene una implementación práctica y elegante de gettimeofday() en Windows. Utiliza el método GetSystemTimeAsFileTime() para obtener un reloj preciso.

Actualización: Aquí hay un enlace activo [editar: vínculo eliminado porque ahora apunta a un sitio de publicidad] que apunta a la implementación a la que se refiere el PO. Tenga en cuenta también que hay un error en la aplicación enlazada:

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) 
    #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 // WRONG 
#else 
    #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL // WRONG 
#endif 

Los valores que se muestran faltan un extra 0 al final (asumieron microsegundos, no el número de intervalos de 100 nanosegundos). Este error se encontró a través del this comment en una página de proyecto de código de Google. Los valores correctos para usar se muestran a continuación: aplicación de gettimeofday

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) 
    #define DELTA_EPOCH_IN_MICROSECS 116444736000000000Ui64 // CORRECT 
#else 
    #define DELTA_EPOCH_IN_MICROSECS 116444736000000000ULL // CORRECT 
#endif 

de PostgreSQL para Windows:

/* 
* gettimeofday.c 
* Win32 gettimeofday() replacement 
* 
* src/port/gettimeofday.c 
* 
* Copyright (c) 2003 SRA, Inc. 
* Copyright (c) 2003 SKC, Inc. 
* 
* Permission to use, copy, modify, and distribute this software and 
* its documentation for any purpose, without fee, and without a 
* written agreement is hereby granted, provided that the above 
* copyright notice and this paragraph and the following two 
* paragraphs appear in all copies. 
* 
* IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, 
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING 
* LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS 
* DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED 
* OF THE POSSIBILITY OF SUCH DAMAGE. 
* 
* THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
* A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS 
* IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, 
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
*/ 

#include "c.h" 

#include <sys/time.h> 


/* FILETIME of Jan 1 1970 00:00:00. */ 
static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL); 

/* 
* timezone information is stored outside the kernel so tzp isn't used anymore. 
* 
* Note: this function is not for Win32 high precision timing purpose. See 
* elapsed_time(). 
*/ 
int 
gettimeofday(struct timeval * tp, struct timezone * tzp) 
{ 
    FILETIME file_time; 
    SYSTEMTIME system_time; 
    ULARGE_INTEGER ularge; 

    GetSystemTime(&system_time); 
    SystemTimeToFileTime(&system_time, &file_time); 
    ularge.LowPart = file_time.dwLowDateTime; 
    ularge.HighPart = file_time.dwHighDateTime; 

    tp->tv_sec = (long) ((ularge.QuadPart - epoch)/10000000L); 
    tp->tv_usec = (long) (system_time.wMilliseconds * 1000); 

    return 0; 
} 
+11

El enlace está roto. –

+1

El segundo enlace ahora también está roto. – Tom

+0

Aquí hay un enlace al código relevante de PostgreSQL: http://git.postgresql.org/gitweb/?p=postgresql.git; a = blob; f = src/puerto/gettimeofday.c; h = 75a91993b74414c0a1c13a2a09ce739cb8aa8a08; hb = HEAD – Tom

4

¿Qué tal:

unsigned long start = GetTickCount(); 
// stuff that needs to be timed 
unsigned long delta = GetTickCount() - start; 

GetTickCount() no es muy precisa, pero probablemente va a funcionar bien. Si ve muchos intervalos de 0, 16 o 31 milisegundos, pruebe el tiempo en intervalos más largos o use una función más precisa como timeGetTime.

Lo que suelo hacer es lo siguiente:

unsigned long deltastack; 
int samples = 0; 
float average; 

unsigned long start = GetTickCount(); 
// stuff that needs to be timed 
unsigned long delta = GetTickCount() - start; 

deltastack += delta; 
if (samples++ == 10) 
{ 
    // total time divided by amount of samples 
    average = (float)deltastack/10.f; 
    deltastack = 0; 
    samples = 0; 
} 
+3

GetTicksCount rollover cada ~ 45.7 días. –

+11

@Shay: ¿Cuándo has visto Windows durante más de 45 días seguidos? OK, sí, no fue necesario ... –

+0

[Función GetTickCount] (https://msdn.microsoft.com/pt-br/library/windows/desktop/ms724408%28v=vs.85%29.aspx) - Recupera la cantidad de milisegundos que han transcurrido desde que se inició el sistema, hasta 49.7 días. – Dinei

1

En su caso me gustaría utilizar la plataforma independiente std::clock

+0

Esta función no devuelve una referencia de tiempo absoluta. – chmike

+0

@chmike no dijo que necesita una referencia de tiempo absoluta –

1

Se puede extraer de QueryPerformanceCounter y QueryPerformanceFrequency. Estos son muy de alta resolución, hasta un tick por cada diez ciclos en algunos temporizadores de hardware.

Cuestiones relacionadas