/[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 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 5 months ago) by william
File size: 7018 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
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 char* Name, const void* buff, u32 sz)
123 {
124 if( ProfRunning )
125 EnterCriticalSection( &ProfModulesLock );
126
127 wxString strName( fromUTF8(Name) );
128 if( !_registeredName( strName ) )
129 ProfModules.push_back( Module( strName, buff, sz ) );
130
131 if( ProfRunning )
132 LeaveCriticalSection( &ProfModulesLock );
133 }
134
135 void ProfilerRegisterSource(const char* Name, const void* function)
136 {
137 if( ProfRunning )
138 EnterCriticalSection( &ProfModulesLock );
139
140 wxString strName( fromUTF8(Name) );
141 if( !_registeredName( strName ) )
142 ProfModules.push_back( Module(strName,function) );
143
144 if( ProfRunning )
145 LeaveCriticalSection( &ProfModulesLock );
146 }
147
148 void ProfilerTerminateSource( const char* Name )
149 {
150 wxString strName( fromUTF8(Name) );
151 for( vector<Module>::const_iterator
152 iter = ProfModules.begin(),
153 end = ProfModules.end(); iter<end; ++iter )
154 {
155 if( iter->name.compare( strName ) == 0 )
156 {
157 ProfModules.erase( iter );
158 break;
159 }
160 }
161 }
162
163 static bool DispatchKnownModules( uint Eip )
164 {
165 bool retval = false;
166 EnterCriticalSection( &ProfModulesLock );
167
168 size_t i;
169 for(i=0;i<ProfModules.size();i++)
170 if (ProfModules[i].Inside(Eip)) break;
171
172 if( i < ProfModules.size() )
173 {
174 ProfModules[i].ticks++;
175 retval = true;
176 }
177
178 LeaveCriticalSection( &ProfModulesLock );
179 return retval;
180 }
181
182 static void MapUnknownSource( uint Eip )
183 {
184 wxChar modulename[512];
185 DWORD sz=GetModuleFromPtr((void*)Eip,modulename,512);
186 wxString modulenam( (sz==0) ? L"[Unknown]" : modulename );
187
188 map<wxString,Module>::iterator iter = ProfUnknownHash.find(modulenam);
189 if (iter!=ProfUnknownHash.end())
190 {
191 iter->second.ticks++;
192 return;
193 }
194
195 Module tmp((sz==0) ? modulenam.c_str() : NULL, (void*)Eip);
196 tmp.ticks++;
197
198 ProfUnknownHash.insert(MapType::value_type(modulenam, tmp));
199 }
200
201 int __stdcall ProfilerThread(void* nada)
202 {
203 ProfUnknownHash.clear();
204 u32 tick_count=0;
205
206 while(ProfRunning)
207 {
208 Sleep(5);
209
210 if (tick_count>500)
211 {
212 wxString rT = L"";
213 wxString rv = L"";
214 u32 subtotal=0;
215 for (size_t i=0;i<ProfModules.size();i++)
216 {
217 wxString t = ProfModules[i].ToString(tick_count);
218 bool b0 = EmuConfig.Cpu.Recompiler.UseMicroVU0;
219 bool b1 = EmuConfig.Cpu.Recompiler.UseMicroVU1;
220 if ( b0 && b1) { if (t.Find(L"sVU") == -1) rT+=t;}
221 else if (!b0 && !b1) { if (t.Find(L"mVU") == -1) rT+=t;}
222 else if (!b0) { if (t.Find(L"mVU0") == -1) rT+=t;}
223 else if (!b1) { if (t.Find(L"mVU1") == -1) rT+=t;}
224 else rT+=t;
225
226 subtotal+=ProfModules[i].ticks;
227 ProfModules[i].ticks=0;
228 }
229
230 rT += wxsFormat( L"| Recs Total: %2.2f%% |", (float)(((double)subtotal*100.0) / (double)tick_count));
231 vector<MapType::mapped_type> lst;
232 for (MapType::iterator i=ProfUnknownHash.begin();i!=ProfUnknownHash.end();i++)
233 {
234 lst.push_back(i->second);
235 }
236
237 sort(lst.begin(),lst.end());
238 for (size_t i=0;i<lst.size();i++)
239 {
240 rv += lst[i].ToString(tick_count);
241 }
242
243 Console.WriteLn( L"Sampling Profiler Results:\n%s\n%s\n", rT.c_str(), rv.c_str() );
244 Console.SetTitle(rT);
245
246 tick_count=0;
247
248 ProfUnknownHash.clear();
249 }
250
251 tick_count++;
252
253 CONTEXT ctx;
254 ctx.ContextFlags = CONTEXT_FULL;
255 GetThreadContext(hEmuThread,&ctx);
256
257 if( !DispatchKnownModules( ctx.Eip ) )
258 {
259 MapUnknownSource( ctx.Eip );
260 }
261
262 if( hMtgsThread != NULL )
263 {
264 GetThreadContext(hMtgsThread,&ctx);
265 if( DispatchKnownModules( ctx.Eip ) )
266 continue;
267 }
268 }
269
270 return -1;
271 }
272
273 void ProfilerInit()
274 {
275 if (ProfRunning)
276 return;
277
278 Console.WriteLn( "Profiler Thread Initializing..." );
279 ProfRunning=true;
280 DuplicateHandle(GetCurrentProcess(),
281 GetCurrentThread(),
282 GetCurrentProcess(),
283 &(HANDLE)hEmuThread,
284 0,
285 FALSE,
286 DUPLICATE_SAME_ACCESS);
287
288 InitializeCriticalSection( &ProfModulesLock );
289
290 hProfThread=CreateThread(0,0,(LPTHREAD_START_ROUTINE)ProfilerThread,0,0,0);
291 SetThreadPriority(hProfThread,THREAD_PRIORITY_HIGHEST);
292 Console.WriteLn( "Profiler Thread Started!" );
293 }
294
295 void ProfilerTerm()
296 {
297 Console.WriteLn( "Profiler Terminating..." );
298 if (!ProfRunning)
299 return;
300
301 ProfRunning=false;
302
303 if( hProfThread != NULL )
304 {
305 ResumeThread(hProfThread);
306 WaitForSingleObject(hProfThread,INFINITE);
307 CloseHandle(hProfThread);
308 }
309
310 if( hEmuThread != NULL )
311 CloseHandle( hEmuThread );
312
313 if( hMtgsThread != NULL )
314 CloseHandle( hMtgsThread );
315
316 DeleteCriticalSection( &ProfModulesLock );
317 Console.WriteLn( "Profiler Termination Done!" );
318 }
319
320 void ProfilerSetEnabled(bool Enabled)
321 {
322 if (!ProfRunning)
323 {
324 if( !Enabled ) return;
325 ProfilerInit();
326 }
327
328 if (Enabled)
329 ResumeThread(hProfThread);
330 else
331 SuspendThread(hProfThread);
332 }

  ViewVC Help
Powered by ViewVC 1.1.22