From: <man...@us...> - 2013-04-10 20:51:02
|
Revision: 1819 http://sourceforge.net/p/modplug/code/1819 Author: manxorist Date: 2013-04-10 20:50:54 +0000 (Wed, 10 Apr 2013) Log Message: ----------- Merged revision(s) 1813 from branches/manx/profiler: [Var] Add a simple realtime profiler (for debugging purposes). (#define USE_PROFILER in Profiler.h to activate, otherwise it does nothing at all) ........ Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters Added Paths: ----------- trunk/OpenMPT/common/Profiler.cpp trunk/OpenMPT/common/Profiler.h Property Changed: ---------------- trunk/OpenMPT/ Index: trunk/OpenMPT =================================================================== --- trunk/OpenMPT 2013-04-10 20:47:43 UTC (rev 1818) +++ trunk/OpenMPT 2013-04-10 20:50:54 UTC (rev 1819) Property changes on: trunk/OpenMPT ___________________________________________________________________ Modified: svn:mergeinfo ## -1,4 +1,5 ## /branches/manx/build-speedup:1586-1589 /branches/manx/header-dependencies-cleanups:1394-1397,1401-1402,1405-1406 +/branches/manx/profiler:1813 /branches/manx/project-files-cleanups:1378-1382 /branches/manx/snddev-fixes:1605-1713 \ No newline at end of property Copied: trunk/OpenMPT/common/Profiler.cpp (from rev 1813, branches/manx/profiler/common/Profiler.cpp) =================================================================== --- trunk/OpenMPT/common/Profiler.cpp (rev 0) +++ trunk/OpenMPT/common/Profiler.cpp 2013-04-10 20:50:54 UTC (rev 1819) @@ -0,0 +1,214 @@ +/* + * 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" +#include <stdlib.h> + + +#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 const 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; + } + char dummy[128]; + sprintf(dummy, "%6.3f", (stats.usage * 100.0)); + ret += cat + " " + std::string(stats.profile.Name) + ": " + std::string(dummy) + "%\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(); +} + + +#endif // USE_PROFILER Copied: trunk/OpenMPT/common/Profiler.h (from rev 1813, branches/manx/profiler/common/Profiler.h) =================================================================== --- trunk/OpenMPT/common/Profiler.h (rev 0) +++ trunk/OpenMPT/common/Profiler.h 2013-04-10 20:50:54 UTC (rev 1819) @@ -0,0 +1,116 @@ +/* + * Profiler.h + * ---------- + * Purpose: Performance measuring + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + + +#include "../common/mutex.h" +#include <string> +#include <vector> + + +//#define USE_PROFILER + + +#ifdef USE_PROFILER + +class Profiler +{ +public: + enum Category + { + GUI, + Audio, + Notify, + CategoriesCount + }; + static std::vector<std::string> GetCategoryNames() + { + std::vector<std::string> ret; + ret.push_back("GUI"); + ret.push_back("Audio"); + ret.push_back("Notify"); + return ret; + } +public: + static void Update(); + static std::string DumpProfiles(); + static std::vector<double> DumpCategories(); +}; + + +class Profile +{ +private: + mutable Util::mutex datamutex; +public: + struct Data + { + uint64 Calls; + uint64 Sum; + int64 Overhead; + uint64 Start; + }; +public: + Data data; + uint64 EnterTime; + Profiler::Category Category; + const char * const Name; + uint64 GetTime() const; + uint64 GetFrequency() const; +public: + Profile(Profiler::Category category, const char *name); + ~Profile(); + void Reset(); + void Enter(); + void Leave(); + class Scope + { + private: + Profile &profile; + public: + Scope(Profile &p) : profile(p) { profile.Enter(); } + ~Scope() { profile.Leave(); } + }; +public: + Data GetAndResetData(); +}; + + +#define OPENMPT_PROFILE_SCOPE(cat, name) \ + static Profile OPENMPT_PROFILE_VAR(cat, name);\ + Profile::Scope OPENMPT_PROFILE_SCOPE_VAR(OPENMPT_PROFILE_VAR); \ +/**/ + + +#define OPENMPT_PROFILE_FUNCTION(cat) OPENMPT_PROFILE_SCOPE(cat, __FUNCTION__) + + +#else // !USE_PROFILER + + +class Profiler +{ +public: + enum Category + { + CategoriesCount + }; + static std::vector<std::string> GetCategoryNames() { return std::vector<std::string>(); } +public: + static void Update() { } + static std::string DumpProfiles() { return std::string(); } + static std::vector<double> DumpCategories() { return std::vector<double>(); } +}; +#define OPENMPT_PROFILE_SCOPE(cat, name) do { } while(0) +#define OPENMPT_PROFILE_FUNCTION(cat) do { } while(0) + + +#endif // USE_PROFILER Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2013-04-10 20:47:43 UTC (rev 1818) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2013-04-10 20:50:54 UTC (rev 1819) @@ -35,6 +35,7 @@ #include "SelectPluginDialog.h" #include "ExceptionHandler.h" #include "PatternClipboard.h" +#include "../common/Profiler.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -783,6 +784,7 @@ ULONG CMainFrame::AudioRead(PVOID pvData, ULONG MaxSamples) //--------------------------------------------------------- { + OPENMPT_PROFILE_FUNCTION(Profiler::Audio); return m_pSndFile->Read(pvData, MaxSamples); } @@ -951,6 +953,7 @@ BOOL CMainFrame::DoNotification(DWORD dwSamplesRead, DWORD SamplesLatency, bool endOfStream) //------------------------------------------------------------------------------------------ { + OPENMPT_PROFILE_FUNCTION(Profiler::Notify); int64 notificationtimestamp = 0; { Util::lock_guard<Util::mutex> lock(m_NotificationBufferMutex); // protect m_TotalSamplesRendered @@ -2100,6 +2103,42 @@ m_SoundCardOptionsDialog->UpdateStatistics(); } +#ifdef USE_PROFILER + { + Profiler::Update(); + + CWnd * cwnd = CWnd::FromHandle(this->m_hWndMDIClient); + CClientDC dc(cwnd); + + int height = 16; + int width = 256; + + std::vector<std::string> catnames = Profiler::GetCategoryNames(); + std::vector<double> cats = Profiler::DumpCategories(); + + for(int i=0; i<Profiler::CategoriesCount; i++) + { + dc.FillSolidRect(0, i * height, (int)(width * cats[i]), height, RGB(255,0,0)); + dc.FillSolidRect((int)(width * cats[i]), i * height, width - (int)(width * cats[i]), height, RGB(192,192,192)); + RECT rect; + cwnd->GetClientRect(&rect); + rect.left += width; + rect.top += i * height; + char dummy[1024]; + sprintf(dummy, "%6.3f%% %s", cats[i] * 100.0, catnames[i].c_str()); + dc.DrawText(dummy, strlen(dummy), &rect, DT_LEFT); + } + + std::string dummy = Profiler::DumpProfiles(); + RECT rect; + cwnd->GetClientRect(&rect); + rect.top += Profiler::CategoriesCount * height; + dc.DrawText(dummy.c_str(), dummy.length(), &rect, DT_LEFT); + + cwnd->Detach(); + } +#endif + } @@ -2290,6 +2329,7 @@ LRESULT CMainFrame::OnUpdatePosition(WPARAM, LPARAM lParam) //--------------------------------------------------------- { + OPENMPT_PROFILE_FUNCTION(Profiler::GUI); Notification *pnotify = (Notification *)lParam; if (pnotify) { Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2013-04-10 20:47:43 UTC (rev 1818) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2013-04-10 20:50:54 UTC (rev 1819) @@ -473,6 +473,10 @@ > </File> <File + RelativePath="..\common\Profiler.cpp" + > + </File> + <File RelativePath="..\common\Reporting.cpp" > </File> @@ -1011,6 +1015,10 @@ > </File> <File + RelativePath="..\common\Profiler.h" + > + </File> + <File RelativePath=".\soundlib\plugins\PluginEventQueue.h" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2013-04-10 20:47:43 UTC (rev 1818) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2013-04-10 20:50:54 UTC (rev 1819) @@ -246,6 +246,7 @@ <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp" /> <ClCompile Include="..\common\misc_util.cpp" /> + <ClCompile Include="..\common\Profiler.cpp" /> <ClCompile Include="..\common\Reporting.cpp" /> <ClCompile Include="..\sounddsp\AGC.cpp" /> <ClCompile Include="..\sounddsp\DSP.cpp" /> @@ -403,6 +404,7 @@ <ClInclude Include="..\common\misc_util.h" /> <ClInclude Include="..\common\mptString.h" /> <ClInclude Include="..\common\mutex.h" /> + <ClInclude Include="..\common\Profiler.h" /> <ClInclude Include="..\common\Reporting.h" /> <ClInclude Include="..\common\StringFixer.h" /> <ClInclude Include="..\common\typedefs.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2013-04-10 20:47:43 UTC (rev 1818) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2013-04-10 20:50:54 UTC (rev 1819) @@ -430,6 +430,9 @@ <ClCompile Include="..\sounddsp\AGC.cpp"> <Filter>Source Files\sounddsp</Filter> </ClCompile> + <ClCompile Include="..\common\Profiler.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="AbstractVstEditor.h"> @@ -786,6 +789,9 @@ <ClInclude Include="Notification.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\common\Profiler.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |