воскресенье, 27 января 2013 г.

Занимаюсь проектом - запуск x86 Windows программ на планшетнике под Windows RT. Нужно было найти наиболее "тормозящие" места в коде, а Visual Studio 2012 не имеет в себе профайлера для АРМ, там даже profile-guided optimization падает на более-менее больших объемах кода. В итоге пришлось в очередной раз писать свой профайлер. Раньше уже раза 3 делал такой же код, еще под Windows Mobile в порте QEMU, и как на зло - код нигде не сохранился.
Поэтому оставляю код тут, на будущее :)

CSet Counters;
bool volatile DumpProfiler=false;
bool ForEachFunc(unsigned int Idx, void *Data, void *Param)
{
 if(Data)
  LogInfo("%08X - %d\n",Idx,Data);
 return true;
}

HANDLE ProfThread=0;
DWORD WINAPI Profiler(
  _In_  LPVOID lpParameter
)
{
 CONTEXT Ctx;
 while(1)
 {
  SuspendThread(ProfThread);
  Ctx.ContextFlags=CONTEXT_CONTROL;
  GetThreadContext(ProfThread,&Ctx);
  ResumeThread(ProfThread);
  Counters.Set(Ctx.Pc,(void*)(1+(DWORD)Counters.Get(Ctx.Pc)));
  if(DumpProfiler)
  {
   Counters.ForEach(ForEachFunc,0);
  }
  Sleep(20);
 }
}

void InitProfiler()
{
 DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),&ProfThread,0,FALSE,DUPLICATE_SAME_ACCESS);
 CreateThread(0,0,Profiler,0,0,0);
}

Код - прост до ужаса. Параллельный поток останавливает интересующий нас поток программы, получает его PC и фиксирует сколько раз на этом месте мы были. Далее - в отладчике стопорим программу, ставим DumpProfiler=true, сортируем/фильтруем полученный лог в Excel-е по адресам - и анализируем в отладчике что где за функция вызывалась.

mamaich, 27.01.2013

Комментариев нет:

Отправить комментарий