Reputation: 33
I'm trying to measure my response time on a serial protocol handshake by pulling QueryPerformanceCounter (QPC). My target system is a win7 on Asrock D1800b Intel Dual Core, compiling with latest version of MinGw (6.3.0-1).
In order to test QPC I have this code:
#include <windows.h>
#include <stdio.h>
void main()
{
//performance timers
LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
for (int i = 0 ; i < 10 ; i++)
{
QueryPerformanceCounter(&StartingTime);
Sleep(10); //ms
QueryPerformanceCounter(&EndingTime);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedMicroseconds.QuadPart *= 1000000; //first scale up counts
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart; //then convert to us
printf("elapsed=%li\n", ElapsedMicroseconds.QuadPart);
}
}
When run on the target system I get: (no other loads)
elapsed=5341
elapsed=14086
elapsed=13818
elapsed=14322
elapsed=15305
elapsed=8867
elapsed=12162
elapsed=14225
elapsed=13333
elapsed=14751
But when run on the developing system (Win10, Intel i5), I get this much consistent result
elapsed=11326
elapsed=11556
elapsed=12630
elapsed=11583
elapsed=11749
elapsed=12644
elapsed=12562
elapsed=11690
elapsed=11726
elapsed=11664
Both above results are examples of a much larger run.
the expected result is somewhere above 10000us.
So, any ideas of what it going on on the target system?
Upvotes: 3
Views: 1201
Reputation: 28941
You probably need to increase the tick rate, which may be defaulted to 64hz (15.625 ms per tick) in order to get Sleep(10) to work as expected. You can increase it to 1000hz (1 ms per tick). This will increase interrupt overhead, but results should be more consistent. Example code fragment:
timeBeginPeriod(1); /* set ticker to 1000 hz */
Sleep(128); /* wait for it to settle */
/* ... benchmark code */
timeEndPeriod(1); /* restore ticker to default */
Note, although Windows is not a real time OS, it is possible in Windows to get a thread to run at a fixed frequency without any drift, and using Sleep(1) when possible to avoid going cpu bound in the fixed frequency thread. Running the thread at a slightly higher priority will help if there are competing threads. This is often used by games that need a "physics engine" thread that runs at a fixed frequency. Example code is included in the answer to this old question:
How to coordinate threads properly based on a fixed cycle frequency?
Example output from a program based on the example in the link, using a fixed frequency of 100hz, run 100 times. There's some variation in each step, but there is no overall drift.
100 deltas in ms:
9.99973023 10.00002346 10.00002346 10.00002346
10.00002346 10.00002346 10.00676775 10.00002346
10.00002346 10.00002346 10.00794067 10.00002346
9.99973023 10.00002346 10.00002346 10.00002346
10.00002346 10.00618129 10.00002346 10.00002346
10.00002346 10.00002346 10.00002346 10.00002346
10.00002346 9.99973023 10.00002346 10.00002346
10.00002346 10.00002346 10.00002346 10.00002346
10.00090315 10.00148961 10.00148961 10.00090315
10.00002346 10.00178284 10.00002346 10.00002346
10.00295576 10.00002346 10.00882036 10.00500837
10.00002346 10.00559483 10.00559483 10.00647452
10.00588806 10.00735421 10.00676775 10.00764744
10.00002346 10.00002346 10.00823390 10.00002346
10.00002346 10.00002346 10.00002346 10.00002346
10.00002346 10.00002346 9.99973023 10.00002346
10.00002346 10.00002346 10.00002346 10.00002346
10.00002346 10.00002346 10.00002346 10.00002346
10.00002346 10.00002346 10.00002346 9.99973023
10.00002346 10.00002346 10.00002346 10.00002346
10.00002346 10.00002346 10.00002346 10.00002346
10.00002346 10.00002346 10.00002346 9.99973023
10.00002346 10.00002346 10.00002346 10.00002346
10.00002346 10.00002346 10.00002346 10.00002346
10.00002346 10.00002346 10.00002346 10.00002346
elapsed time in ms:
1000.000000000000
Upvotes: 1