Я хотел бы измерить время в C, и мне нелегко понимать это, все, что я хочу, что-то вроде этого:
Любая справка ценилась бы.
(Я компилирую в окнах с помощью mingw),
Таймеры высокого разрешения, которые обеспечивают разрешение 1 микросекунда, относятся к системе, поэтому вам придется использовать различные методы для достижения этого на разных платформах ОС. Вы можете быть заинтересованы в проверке следующей статьи, которая реализует кроссплатформенную платформу C ++ класс таймера на основе функций, описанных ниже:
Windows
API Windows обеспечивает чрезвычайно высокую Функции таймера разрешения: QueryPerFormanceCounter ()
, который возвращает текущие истеченные тикалы, а queryperformance преобразование ()
, который возвращает количество клещей в секунду.
Пример:
#include <iostream>
#include <windows.h> // for Windows APIs
using namespace std;
int main()
{
LARGE_INTEGER frequency; // ticks per second
LARGE_INTEGER t1, t2; // ticks
double elapsedTime;
// get ticks per second
QueryPerformanceFrequency(&frequency);
// start timer
QueryPerformanceCounter(&t1);
// do something
// ...
// stop timer
QueryPerformanceCounter(&t2);
// compute and print the elapsed time in millisec
elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
cout << elapsedTime << " ms.\n";
return 0;
}
Linux, Unix и Mac
для системы на основе Unix или Linux вы можете использовать GetTimeOfDay ()
. Эта функция объявляется в «SYS / Time.h».
Пример:
#include <iostream>
#include <sys/time.h> // for gettimeofday()
using namespace std;
int main()
{
struct timeval t1, t2;
double elapsedTime;
// start timer
gettimeofday(&t1, NULL);
// do something
// ...
// stop timer
gettimeofday(&t2, NULL);
// compute and print the elapsed time in millisec
elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms
elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms
cout << elapsedTime << " ms.\n";
return 0;
}
Обратите внимание, что приведенные выше примеры должны быть скомпилированы с C ++, который поддерживает .
Вот заголовочный файл, который я написал, чтобы сделать некоторые простые профилирование производительности (используя ручные таймеры):
#ifndef __ZENTIMER_H__
#define __ZENTIMER_H__
#ifdef ENABLE_ZENTIMER
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#else
typedef unsigned char uint8_t;
typedef unsigned long int uint32_t;
typedef unsigned long long uint64_t;
#endif
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#define ZTIME_USEC_PER_SEC 1000000
/* ztime_t represents usec */
typedef uint64_t ztime_t;
#ifdef WIN32
static uint64_t ztimer_freq = 0;
#endif
static void
ztime (ztime_t *ztimep)
{
#ifdef WIN32
QueryPerformanceCounter ((LARGE_INTEGER *) ztimep);
#else
struct timeval tv;
gettimeofday (&tv, NULL);
*ztimep = ((uint64_t) tv.tv_sec * ZTIME_USEC_PER_SEC) + tv.tv_usec;
#endif
}
enum {
ZTIMER_INACTIVE = 0,
ZTIMER_ACTIVE = (1 << 0),
ZTIMER_PAUSED = (1 << 1),
};
typedef struct {
ztime_t start;
ztime_t stop;
int state;
} ztimer_t;
#define ZTIMER_INITIALIZER { 0, 0, 0 }
/* default timer */
static ztimer_t __ztimer = ZTIMER_INITIALIZER;
static void
ZenTimerStart (ztimer_t *ztimer)
{
ztimer = ztimer ? ztimer : &__ztimer;
ztimer->state = ZTIMER_ACTIVE;
ztime (&ztimer->start);
}
static void
ZenTimerStop (ztimer_t *ztimer)
{
ztimer = ztimer ? ztimer : &__ztimer;
ztime (&ztimer->stop);
ztimer->state = ZTIMER_INACTIVE;
}
static void
ZenTimerPause (ztimer_t *ztimer)
{
ztimer = ztimer ? ztimer : &__ztimer;
ztime (&ztimer->stop);
ztimer->state |= ZTIMER_PAUSED;
}
static void
ZenTimerResume (ztimer_t *ztimer)
{
ztime_t now, delta;
ztimer = ztimer ? ztimer : &__ztimer;
/* unpause */
ztimer->state &= ~ZTIMER_PAUSED;
ztime (&now);
/* calculate time since paused */
delta = now - ztimer->stop;
/* adjust start time to account for time elapsed since paused */
ztimer->start += delta;
}
static double
ZenTimerElapsed (ztimer_t *ztimer, uint64_t *usec)
{
#ifdef WIN32
static uint64_t freq = 0;
ztime_t delta, stop;
if (freq == 0)
QueryPerformanceFrequency ((LARGE_INTEGER *) &freq);
#else
#define freq ZTIME_USEC_PER_SEC
ztime_t delta, stop;
#endif
ztimer = ztimer ? ztimer : &__ztimer;
if (ztimer->state != ZTIMER_ACTIVE)
stop = ztimer->stop;
else
ztime (&stop);
delta = stop - ztimer->start;
if (usec != NULL)
*usec = (uint64_t) (delta * ((double) ZTIME_USEC_PER_SEC / (double) freq));
return (double) delta / (double) freq;
}
static void
ZenTimerReport (ztimer_t *ztimer, const char *oper)
{
fprintf (stderr, "ZenTimer: %s took %.6f seconds\n", oper, ZenTimerElapsed (ztimer, NULL));
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* ! ENABLE_ZENTIMER */
#define ZenTimerStart(ztimerp)
#define ZenTimerStop(ztimerp)
#define ZenTimerPause(ztimerp)
#define ZenTimerResume(ztimerp)
#define ZenTimerElapsed(ztimerp, usec)
#define ZenTimerReport(ztimerp, oper)
#endif /* ENABLE_ZENTIMER */
#endif /* __ZENTIMER_H__ */
Функция ztime ()
- это основная логика, которая вам нужна - она получает текущее время и сохраняет его В 64-битной UINT измеряется в микросекунде. Затем вы можете позже сделать простой математику, чтобы узнать прошедшее время.
Функции Zentimer * ()
являются просто вспомогательными функциями, чтобы получить указатель на простую структуру таймера, ztimer_t
, который записывает время начала и время окончания. ZentimerPause ()
/ ZentimreResume ()
функции позволяют вам, ну, паузу и возобновить таймеру в случае, если вы хотите распечатать некоторую информацию отладки, которую вы не хотите, Например.
Вы можете найти копию файла исходного заголовка в http://www.gnome.org/~fejj/code/zentimer.h в результате шансов, что я запутал HTML ensaping
Использование Time.h Библиотека, попробуйте что-то вроде этого:
long start_time, end_time, elapsed;
start_time = clock();
// Do something
end_time = clock();
elapsed = (end_time - start_time) / CLOCKS_PER_SEC * 1000;
Возьмите лок в этого Однако, если вы хотите точный расчет, я думаю, что вы должны использовать конкретные библиотеки в вашей операционной системе.
Если ваша система Linux поддерживает ее, Clock_getteTime (Clock_Monotonic) должна быть таймером высокого разрешения, который не затронут изменениями системной даты (например, Daemons NTP).
В Linux можно использовать clock_gettime()
:
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); // get initial time-stamp
// ... do stuff ... //
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); // get final time-stamp
double t_ns = (double)(end.tv_sec - start.tv_sec) * 1.0e9 +
(double)(end.tv_nsec - start.tv_nsec);
// subtract time-stamps and
// multiply to get elapsed
// time in ns
Ниже приводится группа универсальных функций C для управления таймером на основе системного вызова gettimeofday (). Все свойства таймера содержатся в одной структуре ticktimer - интервал, который вы хотите, общее время работы с момента инициализации таймера, указатель на желаемый обратный вызов, который вы хотите вызвать, количество раз, когда обратный вызов был вызван. Функция обратного вызова будет выглядеть так:
void your_timer_cb (struct ticktimer *t) {
/* do your stuff here */
}
Чтобы инициализировать и запустить таймер, вызовите ticktimer_init (your_timer, interval, TICKTIMER_RUN, your_timer_cb, 0).
В основном цикле вашей программы вызовите ticktimer_tick (your_timer), и он решит, прошло ли соответствующее количество времени для вызова обратного вызова.
Чтобы остановить таймер, просто вызовите ticktimer_ctl (your_timer, TICKTIMER_STOP).
ticktimer.h:
#ifndef __TICKTIMER_H
#define __TICKTIMER_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#define TICKTIMER_STOP 0x00
#define TICKTIMER_UNCOMPENSATE 0x00
#define TICKTIMER_RUN 0x01
#define TICKTIMER_COMPENSATE 0x02
struct ticktimer {
u_int64_t tm_tick_interval;
u_int64_t tm_last_ticked;
u_int64_t tm_total;
unsigned ticks_total;
void (*tick)(struct ticktimer *);
unsigned char flags;
int id;
};
void ticktimer_init (struct ticktimer *, u_int64_t, unsigned char, void (*)(struct ticktimer *), int);
unsigned ticktimer_tick (struct ticktimer *);
void ticktimer_ctl (struct ticktimer *, unsigned char);
struct ticktimer *ticktimer_alloc (void);
void ticktimer_free (struct ticktimer *);
void ticktimer_tick_all (void);
#endif
ticktimer.c:
#include "ticktimer.h"
#define TIMER_COUNT 100
static struct ticktimer timers[TIMER_COUNT];
static struct timeval tm;
/*!
@brief
Initializes/sets the ticktimer struct.
@param timer
Pointer to ticktimer struct.
@param interval
Ticking interval in microseconds.
@param flags
Flag bitmask. Use TICKTIMER_RUN | TICKTIMER_COMPENSATE
to start a compensating timer; TICKTIMER_RUN to start
a normal uncompensating timer.
@param tick
Ticking callback function.
@param id
Timer ID. Useful if you want to distinguish different
timers within the same callback function.
*/
void ticktimer_init (struct ticktimer *timer, u_int64_t interval, unsigned char flags, void (*tick)(struct ticktimer *), int id) {
gettimeofday(&tm, NULL);
timer->tm_tick_interval = interval;
timer->tm_last_ticked = tm.tv_sec * 1000000 + tm.tv_usec;
timer->tm_total = 0;
timer->ticks_total = 0;
timer->tick = tick;
timer->flags = flags;
timer->id = id;
}
/*!
@brief
Checks the status of a ticktimer and performs a tick(s) if
necessary.
@param timer
Pointer to ticktimer struct.
@return
The number of times the timer was ticked.
*/
unsigned ticktimer_tick (struct ticktimer *timer) {
register typeof(timer->tm_tick_interval) now;
register typeof(timer->ticks_total) nticks, i;
if (timer->flags & TICKTIMER_RUN) {
gettimeofday(&tm, NULL);
now = tm.tv_sec * 1000000 + tm.tv_usec;
if (now >= timer->tm_last_ticked + timer->tm_tick_interval) {
timer->tm_total += now - timer->tm_last_ticked;
if (timer->flags & TICKTIMER_COMPENSATE) {
nticks = (now - timer->tm_last_ticked) / timer->tm_tick_interval;
timer->tm_last_ticked = now - ((now - timer->tm_last_ticked) % timer->tm_tick_interval);
for (i = 0; i < nticks; i++) {
timer->tick(timer);
timer->ticks_total++;
if (timer->tick == NULL) {
break;
}
}
return nticks;
} else {
timer->tm_last_ticked = now;
timer->tick(timer);
timer->ticks_total++;
return 1;
}
}
}
return 0;
}
/*!
@brief
Controls the behaviour of a ticktimer.
@param timer
Pointer to ticktimer struct.
@param flags
Flag bitmask.
*/
inline void ticktimer_ctl (struct ticktimer *timer, unsigned char flags) {
timer->flags = flags;
}
/*!
@brief
Allocates a ticktimer struct from an internal
statically allocated list.
@return
Pointer to the newly allocated ticktimer struct
or NULL when no more space is available.
*/
struct ticktimer *ticktimer_alloc (void) {
register int i;
for (i = 0; i < TIMER_COUNT; i++) {
if (timers[i].tick == NULL) {
return timers + i;
}
}
return NULL;
}
/*!
@brief
Marks a previously allocated ticktimer struct as free.
@param timer
Pointer to ticktimer struct, usually returned by
ticktimer_alloc().
*/
inline void ticktimer_free (struct ticktimer *timer) {
timer->tick = NULL;
}
/*!
@brief
Checks the status of all allocated timers from the
internal list and performs ticks where necessary.
@note
Should be called in the main loop.
*/
inline void ticktimer_tick_all (void) {
register int i;
for (i = 0; i < TIMER_COUNT; i++) {
if (timers[i].tick != NULL) {
ticktimer_tick(timers + i);
}
}
}