1 /* 2 AngelCode Scripting Library 3 Copyright (c) 2003-2016 Andreas Jonsson 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any 7 damages arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any 10 purpose, including commercial applications, and to alter it and 11 redistribute it freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you 14 must not claim that you wrote the original software. If you use 15 this software in a product, an acknowledgment in the product 16 documentation would be appreciated but is not required. 17 18 2. Altered source versions must be plainly marked as such, and 19 must not be misrepresented as being the original software. 20 21 3. This notice may not be removed or altered from any source 22 distribution. 23 24 The original version of this library can be located at: 25 http://www.angelcode.com/angelscript/ 26 27 Andreas Jonsson 28 andreas@angelcode.com 29 */ 30 31 32 // 33 // as_debug.h 34 // 35 36 #ifndef AS_DEBUG_H 37 #define AS_DEBUG_H 38 39 #include "as_config.h" 40 41 #if defined(AS_DEBUG) 42 43 #ifndef AS_WII 44 // The Wii SDK doesn't have these, we'll survive without AS_DEBUG 45 46 #ifndef _WIN32_WCE 47 // Neither does WinCE 48 49 #ifndef AS_PSVITA 50 // Possible on PSVita, but requires SDK access 51 52 #if !defined(_MSC_VER) && (defined(__GNUC__) || defined(AS_MARMALADE)) 53 54 #ifdef __ghs__ 55 // WIIU defines __GNUC__ but types are not defined here in 'conventional' way 56 #include <types.h> 57 typedef signed char int8_t; 58 typedef unsigned char uint8_t; 59 typedef signed short int16_t; 60 typedef unsigned short uint16_t; 61 typedef signed int int32_t; 62 typedef unsigned int uint32_t; 63 typedef signed long long int64_t; 64 typedef unsigned long long uint64_t; 65 typedef float float32_t; 66 typedef double float64_t; 67 #else 68 // Define mkdir for GNUC 69 #include <sys/stat.h> 70 #include <sys/types.h> 71 #define _mkdir(dirname) mkdir(dirname, S_IRWXU) 72 #endif 73 #else 74 #include <direct.h> 75 #endif 76 77 #endif // AS_PSVITA 78 #endif // _WIN32_WCE 79 #endif // AS_WII 80 81 #endif // !defined(AS_DEBUG) 82 83 84 85 #if defined(_MSC_VER) && defined(AS_PROFILE) 86 // Currently only do profiling with MSVC++ 87 88 #include <mmsystem.h> 89 #include <direct.h> 90 #include "as_string.h" 91 #include "as_map.h" 92 #include "as_string_util.h" 93 94 BEGIN_AS_NAMESPACE 95 96 struct TimeCount 97 { 98 double time; 99 int count; 100 double max; 101 double min; 102 }; 103 104 class CProfiler 105 { 106 public: CProfiler()107 CProfiler() 108 { 109 // We need to know how often the clock is updated 110 __int64 tps; 111 if( !QueryPerformanceFrequency((LARGE_INTEGER *)&tps) ) 112 usePerformance = false; 113 else 114 { 115 usePerformance = true; 116 ticksPerSecond = double(tps); 117 } 118 119 timeOffset = GetTime(); 120 } 121 ~CProfiler()122 ~CProfiler() 123 { 124 WriteSummary(); 125 } 126 GetTime()127 double GetTime() 128 { 129 if( usePerformance ) 130 { 131 __int64 ticks; 132 QueryPerformanceCounter((LARGE_INTEGER *)&ticks); 133 134 return double(ticks)/ticksPerSecond - timeOffset; 135 } 136 137 return double(timeGetTime())/1000.0 - timeOffset; 138 } 139 Begin(const char * name)140 double Begin(const char *name) 141 { 142 double time = GetTime(); 143 144 // Add the scope to the key 145 if( key.GetLength() ) 146 key += "|"; 147 key += name; 148 149 // Compensate for the time spent writing to the file 150 timeOffset += GetTime() - time; 151 152 return time; 153 } 154 End(const char *,double beginTime)155 void End(const char * /*name*/, double beginTime) 156 { 157 double time = GetTime(); 158 159 double elapsed = time - beginTime; 160 161 // Update the profile info for this scope 162 asSMapNode<asCString, TimeCount> *cursor; 163 if( map.MoveTo(&cursor, key) ) 164 { 165 cursor->value.time += elapsed; 166 cursor->value.count++; 167 if( cursor->value.max < elapsed ) 168 cursor->value.max = elapsed; 169 if( cursor->value.min > elapsed ) 170 cursor->value.min = elapsed; 171 } 172 else 173 { 174 TimeCount tc = {elapsed, 1, elapsed, elapsed}; 175 map.Insert(key, tc); 176 } 177 178 // Remove the inner most scope from the key 179 int n = key.FindLast("|"); 180 if( n > 0 ) 181 key.SetLength(n); 182 else 183 key.SetLength(0); 184 185 // Compensate for the time spent writing to the file 186 timeOffset += GetTime() - time; 187 } 188 189 protected: WriteSummary()190 void WriteSummary() 191 { 192 // Write the analyzed info into a file for inspection 193 _mkdir("AS_DEBUG"); 194 FILE *fp; 195 #if _MSC_VER >= 1500 && !defined(AS_MARMALADE) 196 fopen_s(&fp, "AS_DEBUG/profiling_summary.txt", "wt"); 197 #else 198 fp = fopen("AS_DEBUG/profiling_summary.txt", "wt"); 199 #endif 200 if( fp == 0 ) 201 return; 202 203 fprintf(fp, "%-60s %10s %15s %15s %15s %15s\n\n", "Scope", "Count", "Tot time", "Avg time", "Max time", "Min time"); 204 205 asSMapNode<asCString, TimeCount> *cursor; 206 map.MoveLast(&cursor); 207 while( cursor ) 208 { 209 asCString key = cursor->key; 210 int count; 211 int n = key.FindLast("|", &count); 212 if( count ) 213 { 214 key = asCString(" ", count) + key.SubString(n+1); 215 } 216 217 fprintf(fp, "%-60s %10d %15.6f %15.6f %15.6f %15.6f\n", key.AddressOf(), cursor->value.count, cursor->value.time, cursor->value.time / cursor->value.count, cursor->value.max, cursor->value.min); 218 219 map.MovePrev(&cursor, cursor); 220 } 221 222 fclose(fp); 223 } 224 225 double timeOffset; 226 double ticksPerSecond; 227 bool usePerformance; 228 229 asCString key; 230 asCMap<asCString, TimeCount> map; 231 }; 232 233 extern CProfiler g_profiler; 234 235 class CProfilerScope 236 { 237 public: CProfilerScope(const char * name)238 CProfilerScope(const char *name) 239 { 240 this->name = name; 241 beginTime = g_profiler.Begin(name); 242 } 243 ~CProfilerScope()244 ~CProfilerScope() 245 { 246 g_profiler.End(name, beginTime); 247 } 248 249 protected: 250 const char *name; 251 double beginTime; 252 }; 253 254 #define TimeIt(x) CProfilerScope profilescope(x) 255 256 END_AS_NAMESPACE 257 258 #else // !(_MSC_VER && AS_PROFILE) 259 260 // Define it so nothing is done 261 #define TimeIt(x) 262 263 #endif // !(_MSC_VER && AS_PROFILE) 264 265 266 267 268 #endif // defined(AS_DEBUG_H) 269 270 271