VC gettickcount () function

Source: Internet
Author: User
Tags emit sleep function

On the VC ++ 6.0 platform, how does one accurately calculate the running time?

 

Unlikely
Computing can pass through
1. Gettickcount, accurate to Ms

Gettickcount () <1>
Yourprogam ()
Gettickcount () <2>
<1>-<2> difference

In C/C ++ programs, time () is often used to obtain the system time, but it is measured in seconds, it is no longer applicable when the time interval is less than 1 second or the precision is higher than 1 second.

At this time, we can use a high-precision timing method that directly uses the timestamp inside the Pentium CPU. We can use the rdtsc command to obtain the timestamp. For details, see kacker's article, x-4-11-8 in programming edition.

The method to obtain the CPU internal timestamp is as follows:

Undefinedview plaincopy to clipboardprint?
Inline unsigned _ int64 getcyclecount ()
{
_ ASM _ emit 0x0f
_ ASM _ emit 0x31
}
Inline unsigned _ int64 getcyclecount ()
{
_ ASM _ emit 0x0f
_ ASM _ emit 0x31
}

Here we get the number of clock cycles since the CPU is powered on. If the CPU clock frequency is 1g, the value changes in one second to about 2 ^ 30, the CPU is a 64-bit counter, so it will not return to zero within 2 ^ 34 seconds (that is, 544.8 years). For the moment, the continuous running time of a machine does not exceed this, so you do not need to consider Counter Overflow.

The above function gets only the number of clock cycles passed by the CPU, not the time. You must use other methods to convert it into time. I wonder if there is any way to obtain the CPU frequency by reading BIOS information. At present, many methods to calculate the CPU frequency are implemented by using the rdtsc command. Sleep (), delay (), and other methods are used to obtain a rough time. Then, based on the changes in the counter during this time period, a rough time corresponding to the corresponding counter change value is obtained.

When the time precision is not high, for example, as long as it is accurate to dozens of milliseconds, sleep () or delay () to calibrate the counter can meet the requirements.

The counters can be encapsulated for easy use as follows:

Watch. h file:

<Undefinedview plaincopy to clipboardprint?
# Ifndef _ watch_h __
# DEFINE _ watch_h __

# Include "sys/types. H"

Typedef _ int64 int64;

Class cwatch
{
Public:
Static void Init ();
Static double gettime ();
Protected:
Static int64 getcyclecount ();
PRIVATE:
Static int64 count_per_second;
Static double starttime;
};

# Endif
# Ifndef _ watch_h __
# DEFINE _ watch_h __

# Include "sys/types. H"

Typedef _ int64 int64;

Class cwatch
{
Public:
Static void Init ();
Static double gettime ();
Protected:
Static int64 getcyclecount ();
PRIVATE:
Static int64 count_per_second;
Static double starttime;
};

# Endif

Watch. cpp file:

Undefinedview plaincopy to clipboardprint?
# Include "watch. H"
# Include <stdlib. h>
# Include <time. h>
# Include <windows. h>

Int64 cwatch: count_per_second = 0;
Double cwatch: starttime = 0.0;

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

Void cwatch: Init ()
{
Int64 start = getcyclecount ();
Sleep (1000); // wait for 1 second to increase the waiting time and the calibration accuracy.
Int64 end = getcyclecount ();
Count_per_second = end-start;

Double currtime = (double) getcyclecount ()/count_per_second;
Time_t realtime = Time (null); // The current time. The precision is only 1 s.
Starttime = Realtime-currtime; // The time when the CPU is powered on.
}

Inline double cwatch: gettime ()
{
Double currtime = (double) getcyclecount ()/count_per_second;
Return currtime + starttime;
}
# Include "watch. H"
# Include <stdlib. h>
# Include <time. h>
# Include <windows. h>

Int64 cwatch: count_per_second = 0;
Double cwatch: starttime = 0.0;

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

Void cwatch: Init ()
{
Int64 start = getcyclecount ();
Sleep (1000); // wait for 1 second to increase the waiting time and the calibration accuracy.
Int64 end = getcyclecount ();
Count_per_second = end-start;

Double currtime = (double) getcyclecount ()/count_per_second;
Time_t realtime = Time (null); // The current time. The precision is only 1 s.
Starttime = Realtime-currtime; // The time when the CPU is powered on.
}

Inline double cwatch: gettime ()
{
Double currtime = (double) getcyclecount ()/count_per_second;
Return currtime + starttime;
}

Because time () is used for counter time marking, the absolute time precision is only seconds, and the time difference precision can reach 1% (determined by the relative precision of sleep ). For example, if you want to get a time difference of 1 ms, the error is only 0.01 Ms.

If you have an accurate CPU frequency method, it will be perfect.

Gettickcount

The gettickcount function retrieves the number of milliseconds that have elapsed since the system was started. It is limited to the resolution of the system timer. To obtain the system timer resolution, use the getsystemtimeadjustment function.

DWORD gettickcount (void );

Parameters
This function has no parameters.
Return values
The return value is the number of milliseconds that have elapsed since the system was started.

Remarks
The elapsed time is stored as a DWORD Value. Therefore, the time will wrap around to zero if the system is run continuously for 49.7 days.

If you need a higher resolution timer, use a multimedia timer or a high-resolution timer.

To obtain the time elapsed since the computer was started, retrieve the system up time counter in the performance data in the Registry key hkey_performance_data. the value returned is an 8-byte value. for more information, see performance monitoring.

Example code
The following example demonstrates how to handle timer wrap around.

DWORD dwstart = gettickcount ();

// Stop if this has taken too long
If (gettickcount ()-dwstart> = timelimit)
Cancel ();
Note that timelimit is the time interval of interest to the application.

For an additional example, see starting a service.

--------------------------------
2. Use Windows native API
Zwquerysysteminformation

Typedef struct _ system_processes {// Information Class 5
Ulong nextentrydelta;
Ulong threadcount;
Ulong reserved1 [6];
Large_integer createtime;
Large_integer usertime;
Large_integer kerneltime;
Unicode_string processname;
Kpriority basepriority;
Ulong processid ;....
Createtime in
Same as above

Http://www.vckbase.com/document/viewdoc? Id = 1301

Precise Timing based on windows in VC

Youzhiyu, Institute of optoelectronic technology, Chinese Emy of Sciences

In the industrial production control system, there are many operations that require timed completion, such as regularly displaying the current time, regularly refreshing the progress bar on the screen, and regularly sending commands and transmitting data to the lower computer. In particular, real-time control systems and data collection systems that require high control performance require precise and scheduled operations.
As we all know, Windows is a message-based system, and any event is executed by sending and receiving messages. In this way, there are some problems. For example, once a computer's CPU is occupied by a process or the system resources are insufficient, messages sent to the message queue are temporarily suspended and cannot be processed in real time. Therefore, you cannot simply use Windows messages to trigger an event with strict timing requirements. In addition, because the access to the underlying computer hardware has been encapsulated in Windows, it is also difficult to achieve accurate timing by directly using the access hardware. Therefore, in actual application, the appropriate timing method should be adopted according to the specific timing precision requirements.
VC provides a lot of time-related functions, using which the control program can accurately complete timing and timing operations. This article describes in detail seven Windows-based precision timing methods in VC, as shown in:

Figure 1 Image Description

Method 1: wm_timer message ing in VC can be used for simple time control. First, call the settimer () function to set the timer interval. For example, settimer (0,200, null) sets the interval of Ms. Then add the scheduled response function ontimer () to the application, and add the Response Processing statement to the function to complete the operation at the scheduled time. This timing method is very simple and can implement certain timing functions, but its timing function is the same as the delay function of the sleep () function. Its accuracy is very low, and the minimum timing accuracy is only 30 ms, CPU usage is low, and the priority of timer messages in multi-task operating systems is very low. Therefore, Timer messages cannot be responded to in a timely manner and often cannot meet the needs of applications in real-time control environments. It can only be used to achieve low timing precision requirements, such as dynamic display of Bitmap. For example, timer1 In the example project.
Method 2: Use the sleep () function in VC to implement latency. Its unit is ms. For example, if the latency is 2 seconds, use sleep (2000 ). The accuracy is very low, and the minimum timing accuracy is only 30 ms. The disadvantage of using the sleep function is that other messages cannot be processed during the delay period. If the time is too long, it will be like a crash, the CPU usage is very high and can only be used in latency programs with low requirements. For example, timer2 In the example project.
Method 3: Use the coledatetime class and coledatetimespan class in combination with the Windows message processing process to achieve latency in seconds. For example, timer3 and timer3_1 In the example project. The following is a two-second latency code:

Coledatetime start_time = coledatetime: getcurrenttime ();
Coledatetimespan end_time = coledatetime: getcurrenttime ()-start_time;
While (end_time.gettotalseconds () <2) // implement latency of 2 seconds
{
MSG;
Getmessage (& MSG, null, 0, 0 );
Translatemessage (& MSG );
Dispatchmessage (& MSG );

// The above four lines can process other messages in a delayed or scheduled period,
// Although this can reduce the CPU usage,
// But it reduces the latency or timing precision, which can be removed in practical applications.
End_time = coledatetime: getcurrenttime ()-start_time;
} // In this way, we can also process other messages during latency.
Method 4: In case of high precision requirements, the gettickcount () function can be used in VC. the return value of this function is DWORD type, the time interval after a computer is started in ms. The accuracy is higher than that of wm_timer message ing. in a short period of time, the timing error is 15 ms, and in a long period of time, the timing error is low. If the timing time is too long, it is like a dead machine, the CPU usage is very high and can only be used in latency programs with low requirements. For example, timer4 and timer4_1 In the example project. The following code can implement accurate timing within 50 ms:
DWORD dwstart = gettickcount ();
DWORD dwend = dwstart;
Do
{
Dwend = gettickcount ()-dwstart;
} While (dwend <50 );
To enable the gettickcount () function to process other messages during a delay or scheduled period, you can change the code:
DWORD dwstart = gettickcount ();
DWORD dwend = dwstart;
Do
{
MSG;
Getmessage (& MSG, null, 0, 0 );
Translatemessage (& MSG );
Dispatchmessage (& MSG );
Dwend = gettickcount ()-dwstart;
} While (dwend <50 );
This can reduce the CPU usage and process other messages during the delay or scheduled period, but reduces the latency or scheduled precision.
Method 5: DWORD timegettime (void), a multimedia timer function similar to the gettickcount () function, returns the number of milliseconds that have elapsed since Windows was started. In its multimedia Windows system, Microsoft provides an API for the precise timer at the bottom layer. The multimedia timer can be used to accurately read the current time of the system, in addition, you can call an event, function, or process within a very precise interval. The difference is that before calling the DWORD timegettime (void) function, you must add winmm. lib and mmsystem. H to the project. Otherwise, the DWORD timegettime (void) function is prompted during compilation. Since this function is scheduled to be controlled through queries, a scheduled cycle should be established to control scheduled events. For example, timer5 and timer5_1 In the example project.
Method 6: Use the multimedia timer timesetevent () function. The timer precision of this function is ms. This function can be used to implement periodic function calls. For example, timer6 and timer6_1 In the example project. The function prototype is as follows:
Mmresult timesetevent (uint udelay,
Uint uresolution,
Lptimecallback lptimeproc,
Word dwuser,
Uint fuevent)
This function sets a scheduled callback event, which can be a one-time event or periodic event. Once an event is activated, the specified callback function is called. If successful, the code of the event identifier is returned. Otherwise, null is returned. Function parameters are described as follows:
Udelay: Specifies the event cycle in milliseconds.
Uresolution: Specify the latency precision in milliseconds. The smaller the value, the higher the timer event resolution. The default value is 1 ms.
Lptimeproc: point to a callback function.
Dwuser: stores user-provided callback data.
Fuevent: Specify the timer event type:
Time_oneshot: Only one event is generated after udelay in milliseconds
Time_periodic: events are generated cyclically every udelay millisecond.
For specific applications, you can call the timesetevent () function to define the tasks to be periodically executed in the lptimeproc callback function (such as scheduled sampling and control ), to complete the event to be processed. Note that the task processing time cannot be greater than the cycle interval. In addition, after the timer is used, call timekillevent () to release it in time.

Method 7: Use the queryperformancefrequency () and queryperformancecounter () functions for scheduled operations with higher precision requirements. These two functions are accurate time functions provided by VC only for Windows 95 and later versions, and require computers to support accurate timers on hardware. For example, timer7, timer7_1, timer7_2, and timer7_3 In the example project.
The following is a prototype of the queryperformancefrequency () and queryperformancecounter () functions:
Bool queryperformancefrequency (large_integer * lpfrequency );
Bool queryperformancecounter (large_integer * lpcount );
The data type arge_integer can be an 8-byte long integer or a combination of two 4-byte long integer values. The specific usage depends on whether the compiler supports 64-bit. This type is defined as follows:
Typedef union _ large_integer
{
Struct
{
DWORD lowpart; // 4-byte integer
Long highpart; // 4-byte integer
};
Longlong quadpart; // 8-byte integer

} Large_integer;
Before timing, call the queryperformancefrequency () function to obtain the clock frequency of the machine's Internal timer, and then call the queryperformancecounter () function before and after a strictly scheduled event, the precise time of the event calendar is calculated based on the difference between the two counts and the clock frequency. Run the following code to implement accurate timing within 1 ms:
Large_integer litmp;
Longlong qpart1, qpart2;
Double dfminus, dffreq, dftim;
Queryperformancefrequency (& litmp );
Dffreq = (double) litmp. quadpart; // obtain the counter clock frequency
Queryperformancecounter (& litmp );
Qpart1 = litmp. quadpart; // obtain the initial value.
Do
{
Queryperformancecounter (& litmp );
Qpart2 = litmp. quadpart; // get the abort Value
Dfminus = (double) (QPart2-QPart1 );
Dftim = dfminus/dffreq; // obtain the corresponding time value, in seconds
} While (dftim <0.001 );
Its timing error is no more than 1 microsecond, and its precision is related to machine configurations such as CPU. The following program is used to test the exact duration of the function sleep (100:
Large_integer litmp;
Longlong qpart1, qpart2;
Double dfminus, dffreq, dftim;
Queryperformancefrequency (& litmp );
Dffreq = (double) litmp. quadpart; // obtain the counter clock frequency
Queryperformancecounter (& litmp );
Qpart1 = litmp. quadpart; // obtain the initial value.
Sleep (100 );
Queryperformancecounter (& litmp );
Qpart2 = litmp. quadpart; // get the abort Value
Dfminus = (double) (QPart2-QPart1 );
Dftim = dfminus/dffreq; // obtain the corresponding time value, in seconds
Due to the error of the sleep () function, each execution result of the preceding program has a slight error. The following code implements precise timing in 1 microsecond:
Large_integer litmp;
Longlong qpart1, qpart2;
Double dfminus, dffreq, dftim;
Queryperformancefrequency (& litmp );
Dffreq = (double) litmp. quadpart; // obtain the counter clock frequency
Queryperformancecounter (& litmp );
Qpart1 = litmp. quadpart; // obtain the initial value.
Do
{
Queryperformancecounter (& litmp );
Qpart2 = litmp. quadpart; // get the abort Value
Dfminus = (double) (QPart2-QPart1 );
Dftim = dfminus/dffreq; // obtain the corresponding time value, in seconds
} While (dftim <0.000001 );
Its timing error generally does not exceed 0.5 microseconds, and its accuracy is related to the configurations of machines such as CPU. (End)

# Include <windows. h>
# Include <iostream>
Using namespace STD;
Class cgetperiodtime {
PRIVATE:
Union utime {
Large_integer _ Li;
Unsigned long _ time;
};
Class initfrequeuency {
Public:
Unsigned long s_frequency;
Initfrequeuency ();
};

Static initfrequeuency s_initfrequeuency;
Utime _ periodtime;
Public:
Void begin () {queryperformancecounter (& _ periodtime. _ Li );}
Unsigned long end ();
};
Cgetperiodtime: initfrequeuency cgetperiodtime: s_initfrequeuency;
Inline cgetperiodtime: initfrequeuency (){
Utime Li;
Queryperformancefrequency (& Li. _ Li );
S_frequency = Li. _ time;
}
Unsigned long cgetperiodtime: end (){
Utime Li;
Queryperformancecounter (& Li. _ Li );
_ Periodtime. _ time = Li. _ time-_ periodtime. _ time;
Return (_ periodtime. _ time * 1000)/s_initfrequeuency.s_frequency;
}
Int main ()
{
Cgetperiodtime time;
Time. Begin ();
Sleep (1000 );
Cout <time. End () <Endl;
Return 0;
}

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

 

Gettickcount

The gettickcount function retrieves the number of milliseconds that have elapsed since the system was started. It is limited to the resolution of the system timer. To obtain the system timer resolution, use the getsystemtimeadjustment function.

DWORD gettickcount (void );

Parameters
This function has no parameters.
Return values
The return value is the number of milliseconds that have elapsed since the system was started.

Remarks
The elapsed time is stored as a DWORD Value. Therefore, the time will wrap around to zero if the system is run continuously for 49.7 days.

If you need a higher resolution timer, use a multimedia timer or a high-resolution timer.

To obtain the time elapsed since the computer was started, retrieve the system up time counter in the performance data in the Registry key hkey_performance_data. the value returned is an 8-byte value. for more information, see performance monitoring.

Example code
The following example demonstrates how to handle timer wrap around.

DWORD dwstart = gettickcount ();

// Stop if this has taken too long
If (gettickcount ()-dwstart> = timelimit)
Cancel ();
Note that timelimit is the time interval of interest to the application.

For an additional example, see starting a service.

--------------------------------
2. Use Windows native API
Zwquerysysteminformation

Typedef struct _ system_processes {// Information Class 5
Ulong nextentrydelta;
Ulong threadcount;
Ulong reserved1 [6];
Large_integer createtime;
Large_integer usertime;
Large_integer kerneltime;
Unicode_string processname;
Kpriority basepriority;
Ulong processid ;....
Createtime in
Same as above

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.