Time Function precision in C Language

Source: Internet
Author: User
Tags emit intel pentium

How to obtain the time in C language? How accurate?

1 use time_t time (time_t * timer) to be accurate to seconds

2 using clock_t clock (), the CPU time is accurate to 1/clocks_per_sec.

3. Calculate the time difference using double difftime (time_t timer1, time_t timer0)

4 Use DWORD gettickcount () precise to milliseconds

5. If you use the ctime class of MFC, you can use ctime: getcurrenttime () to precise to seconds.

6. You can use

Bool queryperformancefrequency (large_integer * lpfrequency)

Obtain the counter frequency of the system.

Bool queryperformancecounter (large_integer * lpperformancecount)

Obtains the counter value.

Then, divide the difference between two counters by frequency to get the time.

7. multimedia timer functions

The following functions are used with multimedia timers.

Timebeginperiod/timeendperiod/timegetdevcaps/timegetsystemtime

//************************************** *******************************

// Use standard C to obtain the current system time

 

I. Time () function

 

The time (& rawtime) function returns the number of seconds from January 1, January 1, 1970, in seconds, and is stored in rawtime.

# Include "time. H"

Void main ()

{

Time_t rawtime;

Struct TM * timeinfo;

Time (& rawtime );

Timeinfo = localtime (& rawtime );

Printf ("/007the current date/time is: % s", asctime (timeinfo ));

Exit (0 );

}

========================

# Include -- the required time function header file

Time_t -- time type (time. H is defined as typedef long time_t; tracing, time_t is long)

Struct TM -- time structure, which is defined as follows:

Int tm_sec;

Int tm_min;

Int tm_hour;

Int tm_mday;

Int tm_mon;

Int tm_year;

Int tm_wday;

Int tm_yday;

Int tm_isdst;

Time (& rawtime); -- get time, in seconds, from January 1, January 1, 1970, stored in rawtime

Localtime (& rawtime); -- convert to local time, TM Time Structure

Asctime () -- convert to standard ASCII time format:

Week Month day hour: minute: second year

 

-----------------------------------------------------------------------------

Ii. Clock () function. Use the clock () function to obtain the millisecond-level time after the system is started. divide it by clocks_per_sec and replace it with the standard C function.

Clock_t clock (void );

# Include

Clock_t T = clock ();

Long sec = T/clocks_per_sec;

It records the clock cycle, and the implementation does not seem very accurate and requires experimental verification;

---------------------------------------------------------------------------

3. gettime (& T); it is said that the time structure of tc2.0 contains millisecond Information

# Include

# Include

Int main (void)

{

Struct time t;

Gettime (& T );

Printf ("the current time is: % 2D: % 02d: % 02d. % 02d/N ",

T. ti_hour, T. ti_min, T. ti_sec, T. ti_hund );

Return 0;

}

Time is a struct, in which the member function ti_hund is millisecond...

 

--------------------------------------------------------------------------------

4. gettickcount (), which is a function commonly used in Windows to calculate the running time;

DWORD dwstart = gettickcount ();

// Run your program code here

DWORD dwend = gettickcount ();

Then (dwend-dwstart) Is your program running time, in milliseconds

This function is only accurate to 55 ms, and one tick is 55 ms.

--------------------------------------------------------------------------------

5. timegettime () T, imegettime () is basically equal to gettickcount (), but the accuracy is higher

DWORD dwstart = timegettime ();

// Run your program code here

DWORD dwend = timegettime ();

Then (dwend-dwstart) Is your program running time, in milliseconds

Although the unit of returned values should be ms, the legend shows that the precision is only 10 ms.

========================================================== =

//************************************** * *************************** Unix

# UNIX time-related, also standard library

//************************************** *******************************

1. The timegm function only converts the struct TM structure to the time_t structure without the time zone information;

Time_t timegm (struct TM * TM );

2. mktime uses time zone information

Time_t mktime (struct TM * TM );

The timelocal function is a GNU extension equivalent to the POSIX function mktime.

Time_t timelocal (struct TM * TM );

3. The gmtime function only converts the time_t structure to the struct TM structure without the time zone information;

Struct TM * gmtime (const time_t * Clock );

4. Use the time zone information for localtime

Struct TM * localtime (const time_t * Clock );

1. Obtain the time and set the time in stime.

Time_t T;

T = time (& T );

2. The stime parameter should be the GMT time, which is set to the local time according to the local time zone;

Int stime (time_t * TP)

3. UTC = true indicates that the Daylight Saving Time is used;

4. The modification time and other information of the file are all stored in GMT. Different systems use localtime to convert the local time after obtaining the modification time;

5. We recommend that you use setup to set the time zone;

6. You can change the time zone to the setting in/etc/sysconfig/clock and then re-apply ln-fs/usr/share/zoneinfo/xxxx/XXX/etc/localtime.

Time_t can only represent the range of 68 years, that is, mktime can only return time_t in the range of 1970-2038

Check whether your system has time_t64, which can indicate a larger time range.

//************************************** * ************************* Windows

# Some differences in window

//************************************** *******************************

 

I. ctime () Class

VC Programming generally uses the ctime class to obtain the current date and time

 

Ctime T = getcurrenttime ();

The systemtime structure contains millisecond information.

Typedef struct _ systemtime {

Word wyear;

Word wmonth;

Word wdayofweek;

Word wday;

Word whour;

Word wminute;

Word wsecond;

Word wmilliseconds;

} Systemtime, * psystemtime;

Systemtime T1;

Getsystemtime (& T1)

Ctime curtime (T1 );

Word MS = t1.wmilliseconds;

Systemtime interval m;

: Getlocaltime (& M );

_ Strtime () in time. h // can only be used in Windows

Char T [11];

_ Strtime (t );

Puts (t );

 

//*****************************

Obtain the current date and time

Ctime TM = ctime: getcurrenttime ();

Cstring STR = TM. Format ("% Y-% m-% d ");

In VC, we can use the ctime class to obtain the current date of the system. The usage is as follows:

Ctime T = ctime: getcurrenttime (); // obtain the system date, stored in T

Int d = T. getday (); // obtain the current date

Int y = T. getyear (); // get the current year

Int M = T. getmonth (); // get the current month

Int H = T. gethour (); // obtain the current time

Int Mm = T. getminute (); // get the current minute

Int S = T. getsecond (); // get the current second

Int W = T. getdayofweek (); // obtain the day of the week. Note that 1 is Sunday and 7 is Saturday.

 

Ii. ctimespan class

To calculate the difference between the two periods, you can use the ctimespan class. The usage is as follows:

Ctime T1 (1999, 3, 19, 22, 15, 0 );

Ctime T = ctime: getcurrenttime ();

Ctimespan span = t-t1; // calculate the interval between the current system time and time t1

Int iday = span. getdays (); // obtain the total number of days of the interval.

Int ihour = span. gettotalhours (); // obtain the total number of hours

Int Imin = span. gettotalminutes (); // obtain the total number of minutes

Int ISEC = span. gettotalseconds (); // gets the total number of seconds

 

 

------------------------------------------------------------------------------

 

3. _ timeb () function

_ Timeb is defined in sys/timeb. h and has four fields.

Dstflag

Millitm

Time

Timezone

Void _ ftime (struct _ timeb * timeptr );

Struct _ timeb timebuffer;

_ Ftime (& timebuffer );

Take the current time: the document can be described in ms. Someone tests it, as if it could only be 16 Ms!

 

 

4. Set a timer

Define timer ID

# Define timerid_jisuanfangshi 2

Set the clock in a proper place, where you need to start its function;

Settimer (timerid_jisuanfangshi, 200, null );

Destroy the clock when no timer is required

Killtimer (timerid_jisuanfangshi );

Message ing corresponding to VC program

Void cjisuan: ontimer (uint nidevent)

{Switch (nidevent )}

Bytes ---------------------------------------------------------------------------------------

# How to set the current system time ------------------------------------- windows

Systemtime m_mylocaltime, * lpsystemtime;

M_mylocaltime.wyear = 2003;

M_mylocaltime.wm;

M_mylocaltime.wday = 1;

M_mylocaltime.whour = 0;

M_mylocaltime.wminute = 0;

M_mylocaltime.wsec;

M_mylocaltime.wmillisec;

Lpsystemtime = & m_mylocaltime;

If (setlocaltime (lpsystemtime) // you cannot change it to setsystemtime ().

MessageBox ("OK! ");

Else

MessageBox ("error! ");

Systemtime m_mylocaltime, * lpsystemtime;

M_mylocaltime.wyear = 2003;

M_mylocaltime.wm;

M_mylocaltime.wday = 1;

Lpsystemtime = & m_mylocaltime;

If (setdate (lpsystemtime) // it cannot be changed to setsystemtime ().

MessageBox ("OK! ");

Else

MessageBox ("error! ");

 

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/khuang2008/archive/2008/12/09/3483274.aspx

 

A method for making a microsecond-level precision timer

When a timer is used, in many cases, only the interval of milliseconds is used. Therefore, you only need to use the following two common methods to meet the requirements. First, after using the settimer function to create a timer, the program passes through the reason that the timer is sent to the wm_timer message in the thread message queue, and get the scheduled effect (do not forget to call the killtimer function paired with settimer when you exit the program ). Second, the gettickcount function can be used to return the time since the computer started. The gettickcount function is called twice and their difference value is controlled to achieve the scheduled effect. This method is the same as the first method, precision is also in milliseconds.

Although the timing effect obtained using these two methods has already met the actual requirements in many cases, their precision is only millisecond-level, and the time interval is required for the hour, the actual timing error is large. The following describes a method for obtaining high-precision timing.

In some computer hardware systems, high-precision operation counters (high-resolution Performance Counter) can be used to obtain high-precision timing intervals, and their accuracy is related to the clock frequency of the CPU. The steps for using this method are as follows:

1. First, call the queryperformancefrequency function to obtain the frequency f of the high-precision running counter. The Unit is the number of times per second (N/S), which is generally large.

2. Call queryperformancecounter at both ends of the Code that requires timing to obtain the values N1 and N2 of the high-precision running counter. The difference between the two values is converted to the time interval by F, t = (n2-n1)/F.

The following example shows how to use this method and its accuracy.

In VC 6.0, use MFC to create a dialog box project named highttimer. The layout of the control in the dialog box panel is as follows:

It contains two static text boxes, two editing boxes, and two buttons. The ID of the edit box above and below is idc_e_test and idc_e_actual, respectively. The member variables added through MFC classwizard also correspond to DWORD m_dwtest and DWORD m_dwact respectively. "Exit" the button ID is idok, "Start test" the button ID is idc_ B _test, And the click message processing function to add this button with MFC classwizard is as follows:

Void chighttimerdlg: onbtest ()

{

// Todo: add your control notification handler code here

Updatedata (true); // obtain the input test time value to the member variable m_dwtest associated with the edit box.

 

Large_integer frequence;

If (! Queryperformancefrequency (& frequence) // gets the frequency of the high-precision running counter. If the hardware does not support this function, false is returned.

MessageBox ("your computer hardware doesn't support the high-resolution performance counter ",

"Not support", mb_iconexclamation | mb_ OK );

 

Large_integer test, RET;

Test. quadpart = frequence. quadpart * m_dwtest/1000000; // converts the number of microseconds to the corresponding number (related to the CPU clock) by frequency, 1 second = 1000000 microseconds

Ret = mysleep (TEST); // call this function to start the delay and return the actual cost.

 

M_dwact = (DWORD) (1000000 * ret. quadpart/frequence. quadpart); // converts to the number of microseconds

 

Updatedata (false); // displayed on the dialog box panel

}

The mysleep function called above is as follows:

 

Large_integer chighttimerdlg: mysleep (large_integer interval)

//////////////////////////////////////// //////////////////////////////////////// /////////////////////////////

// Function: perform the actual latency Function
// Parameter: The interval parameter is the number of time-related delays to be executed.
// Return value: returns the number of time-related values after the function is executed.
//////////////////////////////////////// //////////////////////////////////////// ///////////////////////////

{

Large_integer privious, current, elapse;

 

Queryperformancecounter (& privious );

Current = privious;

 

While (current. quadpart-privious. quadpart <interval. quadpart)

Queryperformancecounter (counter t );

 

Elapse. quadpart = current. quadpart-privious. quadpart;

 

Return elapse;

}

Note: Do not forget to add a function declaration for this function in the header file.

 

Now, you can compile and execute this project. The results are shown in. In my own machine (Pentium 366, 64 M memory) testing, when the test time exceeds 3 microseconds, the accuracy is already very high, at this time, the time when the machine executes its own latency Function Code has little impact on the time needed for latency.

 

The above functions are not encapsulated at the function level due to the needs of the demonstration test. The functions provided below can basically be copied to other programs in the form of global functions.

 

Bool mysleep (DWORD dwinterval)

//////////////////////////////////////// //////////////////////////////////////// /////////////////////////////

// Function: executes the latency function in microseconds.
// Parameter: The interval parameter is the number of required latencies (unit: microseconds)
// Return value: if the computer hardware does not support this function, false is returned. If the function is successfully executed, true is returned.
//////////////////////////////////////// //////////////////////////////////////// ///////////////////////////

{

Bool bnormal = true;

Large_integer frequence, privious, current, interval;

 

If (! Queryperformancefrequency (& frequence ))

{

: MessageBox (null, "your computer hardware doesn't support the high-resolution performance counter ",

"Not support", mb_iconexclamation | mb_ OK); // or other prompts

Return false;

}

 

Interval. quadpart = frequence. quadpart * dwinterval/1000000;

 

Bnormal = bnormal & queryperformancecounter (& privious );

Current = privious;

 

While (current. quadpart-privious. quadpart <interval. quadpart)

Bnormal = bnormal & queryperformancecounter (counter t );

 

Return bnormal;

}

 

It should be noted that, because there are a lot of code in this function, it takes a long time for the machine to execute the code, so the accuracy will be affected when the latency is several microseconds. In fact, when you are familiar with this method, you only need to use the queryperformancefrequency and queryperformancecounter functions to write your own latency code as needed.

 

High-precision timing using CPU timestamps

For performance-focused program developers, a good timing component is both a mentor and a mentor. Timers can be used as program components to help programmers precisely control program processes, and are also a powerful debugging weapon. experienced programmers can determine program performance bottlenecks as soon as possible, or make a convincing performance comparison for different algorithms.

 

On Windows, there are two commonly used Timers: timegettime multimedia timer, which provides millisecond-level timer. However, this accuracy is still too rough for many applications. The other is the queryperformancecount counter, which provides a microsecond-level count as the system differs. For real-time graphics processing, multimedia data stream processing, or real-time system construction programmers, using queryperformancecount/queryperformancefrequency is a basic skill.

 

This article introduces another high-precision timing method that uses the internal timestamp of the Pentium CPU directly. The following discussion mainly benefited from the book Windows graphic programming, page 1-page 17. Interested readers can directly refer to the book. For more information about the rdtsc commands, see the Intel product manual. This article is only used for throwing bricks.

 

In an Intel Pentium CPU, there is a part called "Time Stamp". It is in the format of a 64-bit unsigned integer, records the number of clock cycles that have elapsed since CPU power-on. Because the current CPU clock speed is very high, this component can achieve the time precision of the nanosecond level. This accuracy is incomparable to the above two methods.

 

In a CPU above Pentium, a machine command rdtsc (read time stamp counter) is provided to read the timestamp number and save it in The edX: eax register pair. Since the edX: eax register is the register that stores the function return value in the C ++ language on the Win32 platform, we can regard this instruction as a common function call. Like this:

 

Inline unsigned _ int64 getcyclecount ()

{

_ ASM rdtsc

}

 

But no, because rdtsc is not directly supported by the C ++ Embedded Assembler, we need to use the _ emit pseudo command to directly embed the machine code form 0x0f, 0x31 of the command, as shown below:

 

Inline unsigned _ int64 getcyclecount ()
{
_ ASM _ emit 0x0f
_ ASM _ emit 0x31
}

In the future, when a counter is required, you can call the getcyclecount function twice like using a common Win32 API to compare the difference between the two return values, as shown in the following code:

Unsigned long T;
T = (unsigned long) getcyclecount ();
// Do Something time-intensive...
T-= (unsigned long) getcyclecount ();

On page 15th of Windows graphic programming, a class is written to encapsulate this counter. Interested readers can refer to the code of that class. For more precise timing, the author makes a small improvement by calculating and saving the time for executing the rdtsc command by calling the getcyclecount function twice in a row, to get more accurate timing numbers. But I personally think this improvement is of little significance. According to the test on my machine, this command took about dozens to 100 cycles. It was only a tenth of microsecond in the time on the celon MHZ machine. For most applications, this time is completely negligible, and for those applications that are indeed accurate to the order of nanoseconds, this compensation is too rough.

The advantages of this method are:

1. High precision. The timing accuracy can be achieved directly in nanoseconds (each clock cycle on a 1 GHz CPU is One nanosecond), which is hard to achieve by other timing methods.

2. low cost. The timegettime function needs to be linked to the multi-media library winmm. the Lib and queryperformance * functions are supported by hardware (although I have not seen any machines that are not supported) and the kernel library according to msdn instructions, therefore, both of them can only be used on the Windows platform (for precise timing on the DOS platform, refer to the graphic program developer Guide, which provides detailed instructions on the control timer 8253 ). However, the rdtsc command is a CPU command, which is supported by any machine above the Pentium on the i386 platform, or even without platform restrictions (I believe that the i386 UNIX and Linux methods are also applicable, but there is no conditional test), and the function call overhead is the smallest.

3. There is a direct rate relationship with the CPU clock speed. One count is equivalent to 1/second (CPU clock speed Hz), so that as long as you know the CPU clock speed, you can directly calculate the time. This is different from queryperformancecount. The latter must use queryperformancefrequency to obtain the number of times the current counter is counted per second before it can be converted to time.

The disadvantage of this method is:

1. Most of the existing C/C ++ compilers do not directly support the use of rdtsc commands. You need to program the code by embedding the machine code directly, which is troublesome.

2. High Data jitter. In fact, accuracy and stability are always a conflict for any measurement method. If low-precision timegettime is used for timing, the results are basically the same each time. The rdtsc command has different results each time, with hundreds or even thousands of gaps. This is a contradiction inherent in this method of high precision.

We can use the following formula to calculate the maximum length of timing in this method:

Number of seconds since CPU power-on = number of cycles read by rdtsc/CPU clock speed (HZ)

The maximum number that a 64-bit unsigned integer can express is 1.8 × 10 ^ 19. On my celon 800, it can be timed around (the book says it can be timed on a MHz Pentium in, I don't know how this number is obtained, but it is different from my calculations ). In any case, we don't have to worry about overflow.

The following is a few small examples, which briefly compares the usage and accuracy of the three timing methods.

// Timer1.cpp Timer class that uses the rdtsc command // ktimer class definition can be found in Windows graphic programming p15
// Compilation line: CL timer1.cpp/link user32.lib
# Include
# Include "ktimer. H"
Main ()
{
Unsigned T;
Ktimer timer;
Timer. Start ();
Sleep (1000 );
T = timer. Stop ();
Printf ("lasting time: % d/N", t );
}

// Timer2.cpp uses the timegettime Function
// It must be included, but the Windows header file is complex.
// Simple inclusion is relatively lazy :)
// Compilation line: CL timer2.cpp/link winmm. Lib
# Include
# Include

Main ()
{
DWORD T1, T2;
T1 = timegettime ();
Sleep (1000 );
T2 = timegettime ();
Printf ("begin time: % u/N", T1 );
Printf ("End Time: % u/N", T2 );
Printf ("lasting time: % u/N", (t2-t1 ));
}

// Timer3.cpp uses the queryperformancecounter Function
// Compilation line: CL timer3.cpp/link kernel32.lib
# Include
# Include

Main ()
{
Large_integer T1, T2, TC;
Queryperformancefrequency (& TC );
Printf ("frequency: % u/N", TC. quadpart );
Queryperformancecounter (& T1 );
Sleep (1000 );
Queryperformancecounter (& T2 );
Printf ("begin time: % u/N", t1.quadpart );
Printf ("End Time: % u/N", t2.quadpart );
Printf ("lasting time: % u/N", (t2.quadpart-t1.quadpart ));
}

//////////////////////////////////////// ////////
// The above three examples are the time required to test the sleep for 1 second.
File: // test/test environment: celeon 800 MHz/256 M SDRAM
// Windows 2000 Professional SP2
// Microsoft Visual C ++ 6.0 SP5
//////////////////////////////////////// ////////

The following are the running results of timer1, using the high-precision rdtsc command.
Lasting Time: 804586872

The following is the running result of timer2, using the rough timegettime API
Begin time: 20254254
Endtime: 20255255
Lasting Time: 1001

The following is the running result of timer3, using the queryperformancecount API
Frequency: 3579545
Begin time: 3804729124
Endtime: 3808298836
Lasting Time: 3569712

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.