Официальный сайт студ.городка НГТУ
Программирование и БД » High Resolution Time Measurement and Timers 

#1  15.01.07 21:25

High Resolution Time Measurement and Timers

Укроп написал(а):

High Resolution Time Measurement and Timers, Part I

Last updated Feb 9, 2006.

Standard C++ inherited the <ctime> time and date library from C. While this library offers many useful time and date facilities, it doesn’t support a high-resolution time measurement. The POSIX standard defines extensions to this library which are capable of measuring time in microseconds (millionths of a second) and even nanoseconds (billionths of a second). Let’s see how they are used.
Measuring Time

First, let’s look at a quick reminder. In standard C and C++, you use the time() function to obtain the current timestamp. The time is represented as the number of seconds that have elapsed since The Epoch, or 1/1/1970 at midnight. In a typical 32 bit system, time_t will rollover in 2038. However, as more platforms are gradually moving to a 64 bit time_t, this time bomb so to speak will have disappeared by then.

POSIX defines a fine-grained time measuring function called gettimeofday():

#include <sys/time.h>
#include <unistd.h>
int gettimeofday(struct timeval * tv, struct timezone *tz);

If struct timeval looks familiar, it’s because I discussed awhile ago when I explained non-blocking I/O using select(). Its declaration is repeated here for convenience:

struct timeval
{
int tv_sec; /*seconds*/
int tv_usec; /*microseconds*/
};

struct timezone is declared as follows:

struct timezone
{
int tz_mniuteswest; /*minutes west of Greenwich*/
int tz_dsttime; /*dst correction type*/
};

The actual resolution of gettimeofday() depends on the hardware architecture. Intel processors as well as SPARC machines offer high resolution timers that measure microseconds. Other hardware architectures fall back to the system’s timer, which is typically set to 100 Hz. In such cases, the time resolution will be less accurate.

The following code listing displays the current timestamp in seconds and microseconds:

struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
printf("the current time of day represented as time_t is %d and %d microseconds", tv.tv_sec, tv.tv_usec);

Using Timers

A timer is a resource that enables a process or a thread to schedules an event. A program uses a timer to ask the kernel to notify it when a certain amount of time has elapsed. There are two types of timer: synchronous and asynchronous. When a process uses a timer synchronously, it waits until the timer expires, usually by means of calling sleep() or a similar syscall. Sleeping means that the process is removed from the kernel’s scheduler for a certain amount of time. POSIX defines four different functions for sleeping, each of which measures time in different units.
sleep()

sleep() causes the process to sleep at least nsec seconds or until a <a href=" http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=125">signal</a>; that the process doesn’t ignore is received.

unsigned int sleep (unsigned int nsec);

If sleep() hasn’t slept nsec seconds, it returns the number of seconds left. Otherwise, it returns 0. sleep() is mostly useful for polling a certain resource in fixed intervals of time. For example, a mail client that polls its mail server every 10 minutes can use a loop that contains a sleep(600); call. This is also the most common syscall for sleeping.
usleep()

usleep() causes the process to sleep for at least usec microseconds:

void usleep (unsigned long usec);

usleep() causes the process to sleep for at least usec microseconds. No signals are used in this case. Most implementations use select() to implement this function. It’s equivalent to calling:

timeval tv;
tv.tv_sec=0;
tv.tv_usec=usec;
int select(0, NULL, NULL, NULL, &tv);

nanosleep()

nanosleep() offers a resolution of nanoseconds:

int nanosleep(struct timespec *req, struct timespec * rem);

The struct timespec is declared as follows:

struct timspec
{
long int tv_sec; /*as in timeval*/
long int tv_nsec; /*nanoseconds*/
};

nanosleep() causes the process to sleep at least the amount of time indicated in req or until a signal is received. If nanosleep() terminates earlier due to a signal it returns -1 and rem is filled with the remaining time. nanosleep() offers the highest resolution (theoretically, up to a billionth of a second) although it’s the least portable of these four functions. This function is mostly used in real-time environments, allowing a process to sleep a precise amount of time.

In the second part of this series I will discuss interval timers, a facility that delivers signals on a regular basis to a process.
High Resolution Time Measurement and Timers, Part II

Last updated Feb 16, 2006.

Interval timers deliver signals to a process on a regular basis. I will explain which types of interval timers POSIX defines and how they are used.
Interval Timer Types

POSIX systems associate three timers with each process. Each timer measures a different type of time and delivers a different signal:

    * ITIMER_REAL. A real time clock that measures absolute time, regardless of whether the process is executing, sleeping etc. You can think of it as the equivalent of a clock on the wall. This timer type delivers a SIGALRM signal.
    * ITIMER_VIRTUAL. Counts the process’s execution time, excluding any system calls that the process makes. It delivers a SIGVTALRM signal.
    * ITIMER_PROF. Counts the process’s execution time, including kernel time spent executing system calls on behalf of the process. It excludes any time spent processing interrupts on behalf of the process. This timer delivers a SIFPROF signal.

ITIMER_REAL is used for ordinary polling operations, e.g., obtaining a lock or retrieving new email messages from a server. It is also the only timer supported in certain embedded systems. Various combinations of ITIMER_VIRTUAL and ITIMER_ PROF are typically used in software profiling and performance tuning.
Timely Delivery

Each timer generates a signal within one clock tick after its expiry. A clock tick is equivalent to 10 milliseconds on Intel machines or 1 millisecond on Alpha. If the process is currently running, the kernel will deliver the signal immediately; otherwise the signal is delivered as soon as possible.

To set and query interval timers, use the itimerval struct:

struct itimerval
{
struct timeval it_interval;
struct timeval it_value;
};


it_interval contains the amount of time between signals, e.g., every 60 seconds, and it_value is the remaining amount of until the next signal is sent. For example, if you set an interval timer of type ITIMER_REAL that delivers a signal every 600 seconds, and the last signal was sent 360 seconds ago, it_interval contains the equivalent of 600 seconds, whereas it_value contains 240 seconds.

Recall that timeval is defined like this:

struct timeval
{
int tv_sec; /*seconds*/
int tv_usec; /*microseconds*/
};

To manipulate the timeval members, POSIX defines the following three macros:

    * timerclear(struct timeval). Clears the timeval struct, setting its both fields to zero.
    * timerisset(struct timeval). Checks whether the timeval struct contains at least one element that isn’t zero.
    * timercmp(struct timeval t1, struct timeval t1, operator). Compares two timeval objects. It returns the logical result of

      t0 operator t1;

    * Where operator is a logical operator such as <,==,> and !=. Notice however that <= and >= aren’t supported. Instead, use the

      !timercmp(t1, t2, >);
      !timercmp(t1, t2, <);

Setting and Querying Timers

Two system calls are available for manipulating interval timers. The argument which must contain one of the values: ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF, indicating the specific timer accessed.

#include <sys/time.h>
int getitimer(int which, struct itimerval *val);
int setitimer(int which, struct itimerval *newt, struct itimer * oldt);

getitimer() fills val with the data values associated with the timer which.

getitimer() sets the timer which to newt, and fills in oldt with the previous setting, unless oldt is NULL.

To disable a timer immediately, set its it_value to zero. Setting a timer’s it_interval to zero disables it after the next signal delivery.

Upon successful completion, both getitimer() and setitimer() return 0. Otherwise, -1 is returned and errno is set to indicate the error.

Это не я бляяя...

Offline

Программирование и БД » High Resolution Time Measurement and Timers 

ФутЕр:)

© Hostel Web Group, 2002-2025.   Сообщить об ошибке

Сгенерировано за 0.030 сек.
Выполнено 14 запросов.