/[pcsx2_0.9.7]/trunk/pcsx2/windows/SamplProf.cpp
ViewVC logotype

Contents of /trunk/pcsx2/windows/SamplProf.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 2 months ago) by william
File size: 7258 byte(s)
re-commit (had local access denied errors when committing)
1
2 #include "PrecompiledHeader.h"
3 #include "Utilities/RedtapeWindows.h"
4
5 #include "SamplProf.h"
6 #include <map>
7 #include <algorithm>
8
9 using namespace std;
10
11 DWORD GetModuleFromPtr(IN void* ptr,OUT LPWSTR lpFilename,IN DWORD nSize)
12 {
13 MEMORY_BASIC_INFORMATION mbi;
14 VirtualQuery(ptr,&mbi,sizeof(mbi));
15 return GetModuleFileName((HMODULE)mbi.AllocationBase,lpFilename,nSize);
16 }
17
18 struct Module
19 {
20 uptr base;
21 uptr end;
22 uptr len;
23 wxString name;
24 u32 ticks;
25
26 Module(const wxChar* name, const void* ptr)
27 {
28 if (name!=0)
29 this->name=name;
30 FromAddress(ptr,name==0);
31 ticks=0;
32 }
33 Module(const wxChar* name, const void* b, u32 s)
34 {
35 this->name=name;
36 FromValues(b,s);
37 ticks=0;
38 }
39 bool operator<(const Module &other) const
40 {
41 return ticks>other.ticks;
42 }
43 wxString ToString(u32 total_ticks)
44 {
45 return wxsFormat( L"| %s: %2.2f%% |", name.c_str(), (float)(((double)ticks*100.0) / (double)total_ticks) );
46 }
47 bool Inside(uptr val) { return val>=base && val<=end; }
48 void FromAddress(const void* ptr,bool getname)
49 {
50 wxChar filename[512];
51 wxChar filename2[512];
52 static const void* ptr_old=0;
53
54 if (ptr_old==ptr)
55 return;
56 ptr_old=ptr;
57
58 MEMORY_BASIC_INFORMATION mbi;
59 VirtualQuery(ptr,&mbi,sizeof(mbi));
60 base=(u32)mbi.AllocationBase;
61 GetModuleFileName((HMODULE)mbi.AllocationBase,filename,512);
62 len=(u8*)mbi.BaseAddress-(u8*)mbi.AllocationBase+mbi.RegionSize;
63
64 if (getname)
65 {
66 name=filename;
67 size_t last=name.find_last_of('\\');
68 last=last==name.npos?0:last+1;
69 name=name.substr(last);
70 }
71
72 for(;;)
73 {
74 VirtualQuery(((u8*)base)+len,&mbi,sizeof(mbi));
75 if (!(mbi.Type&MEM_IMAGE))
76 break;
77
78 if (!GetModuleFileName((HMODULE)mbi.AllocationBase,filename2,512))
79 break;
80
81 if (wxStrcmp(filename,filename2)!=0)
82 break;
83 len+=mbi.RegionSize;
84 }
85
86
87 end=base+len-1;
88 }
89 void FromValues(const void* b,u32 s)
90 {
91 base= (uptr)b;
92 len=s;
93 end=base+len-1;
94 }
95 };
96
97 typedef map<wxString,Module> MapType;
98
99 static vector<Module> ProfModules;
100 static MapType ProfUnknownHash;
101
102 static HANDLE hEmuThread = NULL;
103 static HANDLE hMtgsThread = NULL;
104 static HANDLE hProfThread = NULL;
105
106 static CRITICAL_SECTION ProfModulesLock;
107
108 static volatile bool ProfRunning=false;
109
110 static bool _registeredName( const wxString& name )
111 {
112 for( vector<Module>::const_iterator
113 iter = ProfModules.begin(),
114 end = ProfModules.end(); iter<end; ++iter )
115 {
116 if( iter->name.compare( name ) == 0 )
117 return true;
118 }
119 return false;
120 }
121
122 void ProfilerRegisterSource(const wxString& Name, const void* buff, u32 sz)
123 {
124 if( ProfRunning )
125 EnterCriticalSection( &ProfModulesLock );
126
127 if( !_registeredName( Name ) )
128 ProfModules.push_back( Module( Name, buff, sz ) );
129
130 if( ProfRunning )
131 LeaveCriticalSection( &ProfModulesLock );
132 }
133
134 void ProfilerRegisterSource(const wxString& Name, const void* function)
135 {
136 if( ProfRunning )
137 EnterCriticalSection( &ProfModulesLock );
138
139 if( !_registeredName( Name ) )
140 ProfModules.push_back( Module(Name,function) );
141
142 if( ProfRunning )
143 LeaveCriticalSection( &ProfModulesLock );
144 }
145
146 void ProfilerRegisterSource(const char* Name, const void* buff, u32 sz)
147 {
148 ProfilerRegisterSource( fromUTF8(Name), buff, sz );
149 }
150
151 void ProfilerRegisterSource(const char* Name, const void* function)
152 {
153 ProfilerRegisterSource( fromUTF8(Name), function );
154 }
155
156 void ProfilerTerminateSource( const wxString& Name )
157 {
158 for( vector<Module>::const_iterator
159 iter = ProfModules.begin(),
160 end = ProfModules.end(); iter<end; ++iter )
161 {
162 if( iter->name.compare( Name ) == 0 )
163 {
164 ProfModules.erase( iter );
165 break;
166 }
167 }
168 }
169
170 void ProfilerTerminateSource( const char* Name )
171 {
172 ProfilerTerminateSource( fromUTF8(Name) );
173 }
174
175 static bool DispatchKnownModules( uint Eip )
176 {
177 bool retval = false;
178 EnterCriticalSection( &ProfModulesLock );
179
180 size_t i;
181 for(i=0;i<ProfModules.size();i++)
182 if (ProfModules[i].Inside(Eip)) break;
183
184 if( i < ProfModules.size() )
185 {
186 ProfModules[i].ticks++;
187 retval = true;
188 }
189
190 LeaveCriticalSection( &ProfModulesLock );
191 return retval;
192 }
193
194 static void MapUnknownSource( uint Eip )
195 {
196 wxChar modulename[512];
197 DWORD sz=GetModuleFromPtr((void*)Eip,modulename,512);
198 wxString modulenam( (sz==0) ? L"[Unknown]" : modulename );
199
200 map<wxString,Module>::iterator iter = ProfUnknownHash.find(modulenam);
201 if (iter!=ProfUnknownHash.end())
202 {
203 iter->second.ticks++;
204 return;
205 }
206
207 Module tmp((sz==0) ? modulenam.c_str() : NULL, (void*)Eip);
208 tmp.ticks++;
209
210 ProfUnknownHash.insert(MapType::value_type(modulenam, tmp));
211 }
212
213 int __stdcall ProfilerThread(void* nada)
214 {
215 ProfUnknownHash.clear();
216 u32 tick_count=0;
217
218 while(ProfRunning)
219 {
220 Sleep(5);
221
222 if (tick_count>500)
223 {
224 wxString rT = L"";
225 wxString rv = L"";
226 u32 subtotal=0;
227 for (size_t i=0;i<ProfModules.size();i++)
228 {
229 wxString t = ProfModules[i].ToString(tick_count);
230 bool b0 = EmuConfig.Cpu.Recompiler.UseMicroVU0;
231 bool b1 = EmuConfig.Cpu.Recompiler.UseMicroVU1;
232 if ( b0 && b1) { if (t.Find(L"sVU") == -1) rT+=t;}
233 else if (!b0 && !b1) { if (t.Find(L"mVU") == -1) rT+=t;}
234 else if (!b0) { if (t.Find(L"mVU0") == -1) rT+=t;}
235 else if (!b1) { if (t.Find(L"mVU1") == -1) rT+=t;}
236 else rT+=t;
237
238 subtotal+=ProfModules[i].ticks;
239 ProfModules[i].ticks=0;
240 }
241
242 rT += wxsFormat( L"| Recs Total: %2.2f%% |", (float)(((double)subtotal*100.0) / (double)tick_count));
243 vector<MapType::mapped_type> lst;
244 for (MapType::iterator i=ProfUnknownHash.begin();i!=ProfUnknownHash.end();i++)
245 {
246 lst.push_back(i->second);
247 }
248
249 sort(lst.begin(),lst.end());
250 for (size_t i=0;i<lst.size();i++)
251 {
252 rv += lst[i].ToString(tick_count);
253 }
254
255 Console.WriteLn( L"Sampling Profiler Results:\n%s\n%s\n", rT.c_str(), rv.c_str() );
256 Console.SetTitle(rT);
257
258 tick_count=0;
259
260 ProfUnknownHash.clear();
261 }
262
263 tick_count++;
264
265 CONTEXT ctx;
266 ctx.ContextFlags = CONTEXT_FULL;
267 GetThreadContext(hEmuThread,&ctx);
268
269 if( !DispatchKnownModules( ctx.Eip ) )
270 {
271 MapUnknownSource( ctx.Eip );
272 }
273
274 if( hMtgsThread != NULL )
275 {
276 GetThreadContext(hMtgsThread,&ctx);
277 if( DispatchKnownModules( ctx.Eip ) )
278 continue;
279 }
280 }
281
282 return -1;
283 }
284
285 void ProfilerInit()
286 {
287 if (ProfRunning)
288 return;
289
290 Console.WriteLn( "Profiler Thread Initializing..." );
291 ProfRunning=true;
292 DuplicateHandle(GetCurrentProcess(),
293 GetCurrentThread(),
294 GetCurrentProcess(),
295 &(HANDLE)hEmuThread,
296 0,
297 FALSE,
298 DUPLICATE_SAME_ACCESS);
299
300 InitializeCriticalSection( &ProfModulesLock );
301
302 hProfThread=CreateThread(0,0,(LPTHREAD_START_ROUTINE)ProfilerThread,0,0,0);
303 SetThreadPriority(hProfThread,THREAD_PRIORITY_HIGHEST);
304 Console.WriteLn( "Profiler Thread Started!" );
305 }
306
307 void ProfilerTerm()
308 {
309 Console.WriteLn( "Profiler Terminating..." );
310 if (!ProfRunning)
311 return;
312
313 ProfRunning=false;
314
315 if( hProfThread != NULL )
316 {
317 ResumeThread(hProfThread);
318 WaitForSingleObject(hProfThread,INFINITE);
319 CloseHandle(hProfThread);
320 }
321
322 if( hEmuThread != NULL )
323 CloseHandle( hEmuThread );
324
325 if( hMtgsThread != NULL )
326 CloseHandle( hMtgsThread );
327
328 DeleteCriticalSection( &ProfModulesLock );
329 Console.WriteLn( "Profiler Termination Done!" );
330 }
331
332 void ProfilerSetEnabled(bool Enabled)
333 {
334 if (!ProfRunning)
335 {
336 if( !Enabled ) return;
337 ProfilerInit();
338 }
339
340 if (Enabled)
341 ResumeThread(hProfThread);
342 else
343 SuspendThread(hProfThread);
344 }

  ViewVC Help
Powered by ViewVC 1.1.22