123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- /*
- * Profiler.cpp
- * ------------
- * Purpose: Performance measuring
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #include "stdafx.h"
- #include "Profiler.h"
- OPENMPT_NAMESPACE_BEGIN
- #ifdef USE_PROFILER
- class Statistics
- {
- public:
- Profile &profile;
- Profile::Data data;
- double usage;
- Statistics(Profile &p) : profile(p)
- {
- usage = 0.0;
- Update();
- }
- void Update()
- {
- data = profile.GetAndResetData();
- uint64 now = profile.GetTime();
- uint64 timewindow = now - data.Start;
- if(data.Calls > 0 && timewindow > 0)
- {
- usage = (double)data.Sum / (double)timewindow;
- } else
- {
- usage = 0.0;
- }
- }
- };
- struct ProfileBlock
- {
- class Profile * profile;
- const char * name;
- class Statistics * stats;
- };
- static constexpr std::size_t MAX_PROFILES = 1024;
- static ProfileBlock Profiles[ MAX_PROFILES ];
- static std::size_t NextProfile = 0;
- static void RegisterProfile(Profile *newprofile)
- {
- if(NextProfile < MAX_PROFILES)
- {
- Profiles[NextProfile].profile = newprofile;
- Profiles[NextProfile].stats = 0;
- NextProfile++;
- }
- }
- static void UnregisterProfile(Profile *oldprofile)
- {
- for(std::size_t i=0; i<NextProfile; i++) {
- if(Profiles[i].profile == oldprofile) {
- Profiles[i].profile = 0;
- delete Profiles[i].stats;
- Profiles[i].stats = 0;
- }
- }
- }
- void Profiler::Update()
- {
- for(std::size_t i=0; i<NextProfile; i++)
- {
- if(!Profiles[i].stats)
- {
- Profiles[i].stats = new Statistics(*Profiles[i].profile);
- } else
- {
- Profiles[i].stats->Update();
- }
- }
- }
- std::string Profiler::DumpProfiles()
- {
- std::string ret;
- for(std::size_t i=0; i<NextProfile; i++)
- {
- if(Profiles[i].stats)
- {
- Statistics &stats = *Profiles[i].stats;
- std::string cat;
- switch(stats.profile.Category)
- {
- case Profiler::GUI: cat = "GUI"; break;
- case Profiler::Audio: cat = "Audio"; break;
- case Profiler::Notify: cat = "Notify"; break;
- }
- ret += cat + " " + std::string(stats.profile.Name) + ": " + mpt::afmt::right(6, mpt::afmt::fix(stats.usage * 100.0, 3)) + "%\r\n";
- }
- }
- ret += "\r\n";
- return ret;
- }
- std::vector<double> Profiler::DumpCategories()
- {
- std::vector<double> ret;
- ret.resize(Profiler::CategoriesCount);
- for(std::size_t i=0; i<NextProfile; i++)
- {
- if(Profiles[i].stats)
- {
- ret[Profiles[i].profile->Category] += Profiles[i].stats->usage;
- }
- }
- return ret;
- }
- uint64 Profile::GetTime() const
- {
- LARGE_INTEGER ret;
- ret.QuadPart = 0;
- QueryPerformanceCounter(&ret);
- return ret.QuadPart;
- }
- uint64 Profile::GetFrequency() const
- {
- LARGE_INTEGER ret;
- ret.QuadPart = 0;
- QueryPerformanceFrequency(&ret);
- return ret.QuadPart;
- }
- Profile::Profile(Profiler::Category category, const char *name) : Category(category), Name(name)
- {
- data.Calls = 0;
- data.Sum = 0;
- data.Overhead = 0;
- data.Start = GetTime();
- EnterTime = 0;
- RegisterProfile(this);
- }
- Profile::~Profile()
- {
- UnregisterProfile(this);
- }
- Profile::Data Profile::GetAndResetData()
- {
- Profile::Data ret;
- datamutex.lock();
- ret = data;
- data.Calls = 0;
- data.Sum = 0;
- data.Overhead = 0;
- data.Start = GetTime();
- datamutex.unlock();
- return ret;
- }
- void Profile::Reset()
- {
- datamutex.lock();
- data.Calls = 0;
- data.Sum = 0;
- data.Overhead = 0;
- data.Start = GetTime();
- datamutex.unlock();
- }
- void Profile::Enter()
- {
- EnterTime = GetTime();
- }
- void Profile::Leave()
- {
- uint64 LeaveTime = GetTime();
- datamutex.lock();
- data.Calls += 1;
- data.Sum += LeaveTime - EnterTime;
- datamutex.unlock();
- }
- #else // !USE_PROFILER
- MPT_MSVC_WORKAROUND_LNK4221(Profiler)
- #endif // USE_PROFILER
- OPENMPT_NAMESPACE_END
|