2009-09-18 3 views
22

Как я могу штамповать два раза t1 и t2 и получить разницу в миллисекундах в C?Временная метка на языке программирования C

+5

Вы не можете сделать это со стандартным C. Возможные решения у вас будут разными для Linux, Windows, мобильных телефонов, кассовых аппаратов, ... микроволновых печей, ... – pmg

+0

@Christoph: как time(), так и clock() могут возвращать -1 (отбрасывать на соответствующий тип), чтобы показать, что функция недоступна в этой реализации ... и time(), когда доступно, имеет разрешение 1 секунду или хуже. Я просмотрел стандарт, но не нашел никаких жестких ограничений для функции clock(). – pmg

+1

На странице руководства Linux: «Обратите внимание, что время может обернуться. В 32-битной системе, где CLOCKS_PER_SEC равно 1000000, эта функция будет возвращать то же значение приблизительно каждые 72 минуты ". Чтобы получить время процессора, getrusage() лучше, хотя часы являются частью ANSI C, но getrusage/gettimeofday() нет. – user172818

ответ

28

Это даст вам время в секундах + микросекунд

#include <sys/time.h> 
struct timeval tv; 
gettimeofday(&tv,NULL); 
tv.tv_sec // seconds 
tv.tv_usec // microseconds 
0

U может попробовать процедуры в C библиотеку времени (time.h). Плюс посмотрите на clock() в том же lib. Он дает часовые метки с момента запуска прога. Но вы можете сохранить его значение до операции, на которой хотите сосредоточиться, а затем после этой операции захватите клики снова и найдите разницу между тем, чтобы получить разницу во времени. Код

3

Используйте @Arkaitz Хименеса, чтобы получить два timevals:

#include <sys/time.h> 
//... 
struct timeval tv1, tv2, diff; 

// get the first time: 
gettimeofday(&tv1, NULL); 

// do whatever it is you want to time 
// ... 

// get the second time: 
gettimeofday(&tv2, NULL); 

// get the difference: 

int result = timeval_subtract(&diff, &tv1, &tv2); 

// the difference is storid in diff now. 

Пример кода для timeval_subtract можно найти на this web site:

/* Subtract the `struct timeval' values X and Y, 
    storing the result in RESULT. 
    Return 1 if the difference is negative, otherwise 0. */ 

int 
timeval_subtract (result, x, y) 
     struct timeval *result, *x, *y; 
{ 
    /* Perform the carry for the later subtraction by updating y. */ 
    if (x->tv_usec < y->tv_usec) { 
    int nsec = (y->tv_usec - x->tv_usec)/1000000 + 1; 
    y->tv_usec -= 1000000 * nsec; 
    y->tv_sec += nsec; 
    } 
    if (x->tv_usec - y->tv_usec > 1000000) { 
    int nsec = (x->tv_usec - y->tv_usec)/1000000; 
    y->tv_usec += 1000000 * nsec; 
    y->tv_sec -= nsec; 
    } 

    /* Compute the time remaining to wait. 
     tv_usec is certainly positive. */ 
    result->tv_sec = x->tv_sec - y->tv_sec; 
    result->tv_usec = x->tv_usec - y->tv_usec; 

    /* Return 1 if result is negative. */ 
    return x->tv_sec < y->tv_sec; 
} 
+0

Код в timeval_subtract является злым, потому что он изменяет входное значение y. Было бы неплохо, если бы входы были двумя значениями structvalval, а не указателями. Но при оценке «x - y» вы обычно не ожидаете, что вычисление изменит значение, сохраненное в «y». –

+0

@ Джонатан, правда. Хотя простое изменение его на реализацию по-копии могло бы решить эту проблему – Glen

+0

Согласен. Я бы это исправить, но я не могу проверить, что мои изменения будут компилироваться в данный момент, поэтому я решил, что оставлю это как есть. – Bill

6

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

В Windows используйте GetTickCount(). Вот как:

DWORD dwStart = GetTickCount(); 
... 
... process you want to measure elapsed time for 
... 
DWORD dwElapsed = GetTickCount() - dwStart; 

dwElapsed теперь количество истекших миллисекунд.

В Linux, используйте часы() и CLOCKS_PER_SEC делать то же самое.

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

Кроме того, в Windows по крайней мере вы можете получить гораздо лучшее, чем стандартное временное разрешение. Обычно, если вы вызвали GetTickCount() в узком цикле, вы увидите, что он прыгает на 10-50 каждый раз, когда он изменился. Это из-за кванта времени, используемого планировщиком потоков Windows. Это больше или меньше времени, которое дает каждому потоку, прежде чем переключиться на что-то другое. Если вы делаете:

timeBeginPeriod(1); 

в начале программы или процесса и:

timeEndPeriod(1); 

в конце, то квантовая изменится на 1 мс, и вы получите гораздо больше времени разрешение на вызов GetTickCount(). Тем не менее, это делает тонкие изменения в том, как весь ваш компьютер запускает процессы, поэтому имейте это в виду. Однако Windows Media Player и многие другие делают это в обычном режиме, поэтому я не слишком беспокоюсь об этом.

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

8

Стандарт C99:

#include <time.h> 

time_t t0 = time(0); 
// ... 
time_t t1 = time(0); 
double datetime_diff_ms = difftime(t1, t0) * 1000.; 

clock_t c0 = clock(); 
// ... 
clock_t c1 = clock(); 
double runtime_diff_ms = (c1 - c0) * 1000./CLOCKS_PER_SEC; 

Точность типов зависит от реализации, то есть разница даты и времени может возвращать только полные секунды.

+0

Времени datetime возвращает полные секунды в лучшем случае. Если я правильно интерпретировал Стандарт, time(), когда он не возвращает (time_t) -1, не гарантируется возврат новых значений каждую секунду: он может иметь разрешение 5 секунд или 1 минуту, например. – pmg

+2

@pmg: точность определена, например, на моей системе 'time()' имеет разрешение '1s'; точность 'clock()' обычно как можно выше, но она измеряет время выполнения, а не datetime. – Christoph

1

Также осознавая взаимодействия между clock() и usleep(). usleep() приостанавливает программу, а clock() только измеряет время выполнения программы.

Если бы лучше использовать gettimeofday(), как указано here

5
/* 
Returns the current time. 
*/ 

char *time_stamp(){ 

char *timestamp = (char *)malloc(sizeof(char) * 16); 
time_t ltime; 
ltime=time(NULL); 
struct tm *tm; 
tm=localtime(&ltime); 

sprintf(timestamp,"%04d%02d%02d%02d%02d%02d", tm->tm_year+1900, tm->tm_mon, 
    tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); 
return timestamp; 
} 


int main(){ 

printf(" Timestamp: %s\n",time_stamp()); 
return 0; 

} 

Выход: TIMESTAMP: 20110912130940 // 2011 сентября 12 13:09:40

+0

Вместо форматирования данных вы можете использовать asctime (tm), который возвращает строку. –

2

как об этом решении? Я не видел ничего подобного в моем поиске. Я пытаюсь избежать разделения и упростить решение.

struct timeval cur_time1, cur_time2, tdiff; 

    gettimeofday(&cur_time1,NULL); 
    sleep(1); 
    gettimeofday(&cur_time2,NULL); 

    tdiff.tv_sec = cur_time2.tv_sec - cur_time1.tv_sec; 
    tdiff.tv_usec = cur_time2.tv_usec + (1000000 - cur_time1.tv_usec); 

    while(tdiff.tv_usec > 1000000) 
    { 
     tdiff.tv_sec++; 
     tdiff.tv_usec -= 1000000; 
     printf("updated tdiff tv_sec:%ld tv_usec:%ld\n",tdiff.tv_sec, tdiff.tv_usec); 
    } 

    printf("end tdiff tv_sec:%ld tv_usec:%ld\n",tdiff.tv_sec, tdiff.tv_usec); 
Смежные вопросы