00001 00031 #include "linden_common.h" 00032 00033 #include "llfasttimer.h" 00034 00035 #include "llprocessor.h" 00036 00037 00038 #if LL_WINDOWS 00039 #elif LL_LINUX || LL_SOLARIS 00040 #include <sys/time.h> 00041 #include <sched.h> 00042 #elif LL_DARWIN 00043 #include <sys/time.h> 00044 #else 00045 #error "architecture not supported" 00046 #endif 00047 00049 // statics 00050 00051 int LLFastTimer::sCurDepth = 0; 00052 U64 LLFastTimer::sStart[LLFastTimer::FTM_MAX_DEPTH]; 00053 U64 LLFastTimer::sCounter[LLFastTimer::FTM_NUM_TYPES]; 00054 U64 LLFastTimer::sCountHistory[LLFastTimer::FTM_HISTORY_NUM][LLFastTimer::FTM_NUM_TYPES]; 00055 U64 LLFastTimer::sCountAverage[LLFastTimer::FTM_NUM_TYPES]; 00056 U64 LLFastTimer::sCalls[LLFastTimer::FTM_NUM_TYPES]; 00057 U64 LLFastTimer::sCallHistory[LLFastTimer::FTM_HISTORY_NUM][LLFastTimer::FTM_NUM_TYPES]; 00058 U64 LLFastTimer::sCallAverage[LLFastTimer::FTM_NUM_TYPES]; 00059 S32 LLFastTimer::sCurFrameIndex = -1; 00060 S32 LLFastTimer::sLastFrameIndex = -1; 00061 int LLFastTimer::sPauseHistory = 0; 00062 int LLFastTimer::sResetHistory = 0; 00063 00064 F64 LLFastTimer::sCPUClockFrequency = 0.0; 00065 00067 00068 // 00069 // CPU clock/other clock frequency and count functions 00070 // 00071 00072 #if LL_WINDOWS 00073 00074 U64 get_cpu_clock_count() 00075 { U32 hi,lo; 00076 00077 __asm 00078 { 00079 _emit 0x0f 00080 _emit 0x31 00081 mov lo,eax 00082 mov hi,edx 00083 } 00084 00085 U64 ret = hi; 00086 ret *= 4294967296L; 00087 ret |= lo; 00088 return ret; 00089 }; 00090 00091 #endif // LL_WINDOWS 00092 00093 00094 #if (LL_LINUX || LL_SOLARIS) && (defined(__i386__) || defined(__amd64__)) 00095 U64 get_cpu_clock_count() 00096 { 00097 U64 x; 00098 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); 00099 return x; 00100 } 00101 #endif 00102 00103 #if LL_DARWIN || (LL_SOLARIS && defined(__sparc__)) 00104 // 00105 // Mac implementation of CPU clock 00106 // 00107 // Just use gettimeofday implementation for now 00108 00109 U64 get_cpu_clock_count() 00110 { 00111 return get_clock_count(); 00112 } 00113 #endif 00114 00116 00117 //static 00118 #if LL_LINUX || LL_DARWIN || LL_SOLARIS 00119 // Both Linux and Mac use gettimeofday for accurate time 00120 U64 LLFastTimer::countsPerSecond() 00121 { 00122 return 1000000; // microseconds, so 1 Mhz. 00123 } 00124 #else 00125 U64 LLFastTimer::countsPerSecond() 00126 { 00127 if (!sCPUClockFrequency) 00128 { 00129 CProcessor proc; 00130 sCPUClockFrequency = proc.GetCPUFrequency(50); 00131 } 00132 return U64(sCPUClockFrequency); 00133 } 00134 #endif 00135 00136 void LLFastTimer::reset() 00137 { 00138 countsPerSecond(); // good place to calculate clock frequency 00139 00140 if (sCurDepth != 0) 00141 { 00142 llerrs << "LLFastTimer::Reset() when sCurDepth != 0" << llendl; 00143 } 00144 if (sPauseHistory) 00145 { 00146 sResetHistory = 1; 00147 } 00148 else if (sResetHistory) 00149 { 00150 sCurFrameIndex = -1; 00151 sResetHistory = 0; 00152 } 00153 else if (sCurFrameIndex >= 0) 00154 { 00155 int hidx = sCurFrameIndex % FTM_HISTORY_NUM; 00156 for (S32 i=0; i<FTM_NUM_TYPES; i++) 00157 { 00158 sCountHistory[hidx][i] = sCounter[i]; 00159 sCountAverage[i] = (sCountAverage[i]*sCurFrameIndex + sCounter[i]) / (sCurFrameIndex+1); 00160 sCallHistory[hidx][i] = sCalls[i]; 00161 sCallAverage[i] = (sCallAverage[i]*sCurFrameIndex + sCalls[i]) / (sCurFrameIndex+1); 00162 } 00163 sLastFrameIndex = sCurFrameIndex; 00164 } 00165 else 00166 { 00167 for (S32 i=0; i<FTM_NUM_TYPES; i++) 00168 { 00169 sCountAverage[i] = 0; 00170 sCallAverage[i] = 0; 00171 } 00172 } 00173 00174 sCurFrameIndex++; 00175 00176 for (S32 i=0; i<FTM_NUM_TYPES; i++) 00177 { 00178 sCounter[i] = 0; 00179 sCalls[i] = 0; 00180 } 00181 sCurDepth = 0; 00182 } 00183