diff options
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/common/Profiler.cpp')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/common/Profiler.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/common/Profiler.cpp b/Src/external_dependencies/openmpt-trunk/common/Profiler.cpp new file mode 100644 index 00000000..c73dab88 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/common/Profiler.cpp @@ -0,0 +1,221 @@ +/* + * 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 |