source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Timer/RDTSCTimer.cpp @ 2777

Revision 2777, 5.8 KB checked in by mattausch, 16 years ago (diff)
Line 
1// ===========================================================================
2//  (C) 1999 Vienna University of Technology
3// ===========================================================================
4//  NAME:       RDTSCTimer
5//  TYPE:       c++ code
6//  PROJECT:    Urban Viz/yare (yet another rendering engine)
7//  CONTENT:    Very accurate timer for Win32 systems
8//                              (uses QueryPerformanceCounter, usually microseconds)
9//  VERSION:    0.1
10// ===========================================================================
11//  AUTHORS:    mw      Michael Wimmer
12// ===========================================================================
13//  HISTORY:
14//
15//  15-jul-99 14:00:00  mw      created
16// ===========================================================================
17//  $Header: /usr/local/cvsyare/cvsyare/src/yareutils/RDTSCTimer.cpp,v 1.2 2005/03/07 17:32:09 wimmer Exp $
18// ===========================================================================
19
20#ifdef WIN32
21
22#include "RDTSCTimer.h"
23
24#include "merror.h"
25
26
27// ---------------------------------------------------------------------------
28//  class RDTSCTimer implementation
29// ---------------------------------------------------------------------------
30
31LARGE_INTEGER RDTSCTimer::frequency = {0,1};
32bool RDTSCTimer::isinitialized = false;
33bool RDTSCTimer::available = false;
34
35// this retrieves the timer frequency - will be called by constructor
36void RDTSCTimer::InitClass(bool verbose)
37{
38        isinitialized = true;
39        available = true;
40
41    if (verbose)
42                OUT1(("Calibrating RDTSC-Timer at real-time priority...."));
43
44        // Increase process class
45        HANDLE  hProcess = GetCurrentProcess();
46        DWORD   iPriorityClass = GetPriorityClass(hProcess);
47        ASM_ELSE(iPriorityClass, "couldnt change priority class")
48                SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
49       
50        // Increase thread priority
51        HANDLE  hThread = GetCurrentThread();
52        DWORD   iPriority = GetThreadPriority(hThread);
53        ASM_ELSE(iPriority != THREAD_PRIORITY_ERROR_RETURN, "couldnt change thread priority")
54                SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
55       
56
57        // Measure CPU frequency
58        LARGE_INTEGER PerfFreq;
59    LARGE_INTEGER  calStart, calEnd;
60    LARGE_INTEGER  perfStart, perfEnd;
61       
62        // warmup
63        RDTSC(calStart);
64        RDTSC(calStart);
65        RDTSC(calStart);
66
67        ASM_RET( QueryPerformanceFrequency( &PerfFreq ), "QueryPerformanceCounter not available for calibrating!");
68        QueryPerformanceCounter( &perfStart );
69    RDTSC(calStart);
70                LARGE_INTEGER endmark; endmark.QuadPart = perfStart.QuadPart + PerfFreq.QuadPart;
71                do {
72                        QueryPerformanceCounter( &perfEnd );
73                } while (perfEnd.QuadPart < endmark.QuadPart);
74    RDTSC(calEnd);
75   
76
77        // number of Bench cycles counted
78        LARGE_INTEGER perfcounts; perfcounts.QuadPart = perfEnd.QuadPart - perfStart.QuadPart;
79        // number of RDTSC cycles counted
80        LARGE_INTEGER calcounts; calcounts.QuadPart = calEnd.QuadPart - calStart.QuadPart;
81        // note: this might overflow if processor is over 6GHz:
82        unsigned __int64 temp = calcounts.QuadPart * PerfFreq.QuadPart;
83        frequency.QuadPart = temp / perfcounts.QuadPart;
84
85        //if (verbose)
86        //      OUT1( SV(perfcounts.LowPart)<<SV(calcounts.LowPart)<<SV(calcounts.HighPart)<<SV(PerfFreq.LowPart));
87
88    //
89    // Number of calibration loops
90    //
91        #define CALIBRATION_LOOPS 50000
92
93        ///--- measure overhead of different calling conventions
94       
95        ULONG  i;
96       
97        //-- Start/Elapsed overhead
98
99        RDTSCTimer mytimer2;
100    RDTSC(calStart);
101        for( i = 0; i < CALIBRATION_LOOPS; i++ ) {
102        PERF_ENTRY(mytimer2);
103        PERF_EXIT(mytimer2);
104    }
105    RDTSC(calEnd);
106
107        LARGE_INTEGER   CalEntryExitCycles, CalCountedCycles;
108    CalEntryExitCycles.QuadPart = (calEnd.QuadPart - calStart.QuadPart)/CALIBRATION_LOOPS;
109        CalCountedCycles.QuadPart = mytimer2.total_count.QuadPart / CALIBRATION_LOOPS;
110
111
112/*      RDTSCTimer mytimer;
113    RDTSC(calStart);
114        for( i = 0; i < CALIBRATION_LOOPS; i++ ) {
115        mytimer.Start();
116        mytimer.Elapsed();
117    }
118    RDTSC(calEnd);
119
120        LARGE_INTEGER   CalStartElapsedCycles;
121    CalStartElapsedCycles.QuadPart = (calEnd.QuadPart - calStart.QuadPart)/CALIBRATION_LOOPS;
122   
123
124        RDTSCTimer mytimer3;
125    RDTSC(calStart);
126        for( i = 0; i < CALIBRATION_LOOPS; i++ ) {
127        mytimer3.Entry();
128                mytimer3.Exit();
129    }
130    RDTSC(calEnd);
131
132        LARGE_INTEGER   CalEntryExitCycles2, CalCountedCycles2;
133    CalEntryExitCycles2.QuadPart = (calEnd.QuadPart - calStart.QuadPart)/CALIBRATION_LOOPS;
134        CalCountedCycles2.QuadPart = mytimer3.total_count.QuadPart / CALIBRATION_LOOPS;
135*/
136
137    RDTSC(calStart);
138        for( i = 0; i < CALIBRATION_LOOPS; i++ ) {
139                QueryPerformanceCounter( &perfStart );
140                QueryPerformanceCounter( &perfStart );
141    }
142    RDTSC(calEnd);
143
144        LARGE_INTEGER   PerfEntryExitCycles;
145        PerfEntryExitCycles.QuadPart = (calEnd.QuadPart - calStart.QuadPart)/CALIBRATION_LOOPS;
146       
147        // Restore thread and process priority
148        if (iPriority != THREAD_PRIORITY_ERROR_RETURN)
149                SetThreadPriority(hThread, iPriority);
150
151        if (iPriorityClass)
152                SetPriorityClass(hProcess, iPriorityClass);
153       
154
155        if (verbose)
156        {
157                OUT2("RDTSC frequency: " << frequency.LowPart << ", QueryPerformanceCounter frequency: " << PerfFreq.LowPart);
158                OUT2("Overhead for timer calls in clock cycles:");
159                //OUT2(CalStartElapsedCycles.LowPart << " for timer.start;timer.elapsed;");
160                OUT2(CalEntryExitCycles.LowPart << " for PERF_ENTRY/PERF_EXIT, cycles counted per call: " << CalCountedCycles.LowPart);
161                //OUT2(CalEntryExitCycles2.LowPart << " for Entry()/Exit(), cycles counted per call: " << CalCountedCycles2.LowPart);
162                OUT2(PerfEntryExitCycles.LowPart << " for QueryPerformanceCounter twice");
163        }
164}
165
166/// returns the frequency
167double RDTSCTimer::GetFrequency(bool verbose)
168{
169        if (!isinitialized)
170                InitClass(verbose);
171       
172        return (double)frequency.QuadPart;
173}
174
175#endif // WIN32
Note: See TracBrowser for help on using the repository browser.