2
0

PerformanceStatistician.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Asset/AssetManagerBus.h>
  9. #include <AzCore/RTTI/BehaviorContext.h>
  10. #include <ScriptCanvas/Asset/RuntimeAsset.h>
  11. #include <ScriptCanvas/Execution/ExecutionBus.h>
  12. #include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h>
  13. #include <ScriptCanvas/PerformanceStatistician.h>
  14. #include <ScriptCanvas/PerformanceTracker.h>
  15. #include <ScriptCanvas/SystemComponent.h>
  16. namespace ScriptCanvas
  17. {
  18. namespace Execution
  19. {
  20. void PerformanceStatistics::CalculateSecondary()
  21. {
  22. scriptCostPercent = aznumeric_cast<double>(report.tracking.timing.totalTime) / aznumeric_cast<double>(duration);
  23. }
  24. AZStd::string ToConsoleString(const PerformanceStatistics& stats)
  25. {
  26. AZStd::string consoleString("\n");
  27. const double initializingMs = aznumeric_caster(stats.report.tracking.timing.initializationTime / 1000.0);
  28. const double executionMs = aznumeric_caster(stats.report.tracking.timing.executionTime / 1000.0);
  29. const double latentMs = aznumeric_caster(stats.report.tracking.timing.latentTime / 1000.0);
  30. const double totalMs = aznumeric_caster(stats.report.tracking.timing.totalTime / 1000.0);
  31. consoleString += "[ INITIALIZE] ";
  32. consoleString += AZStd::string::format("%7.3f ms \n", initializingMs);
  33. consoleString += "[ EXECUTION] ";
  34. consoleString += AZStd::string::format("%7.3f ms \n", executionMs);
  35. consoleString += "[ LATENT] ";
  36. consoleString += AZStd::string::format("%7.3f ms \n", latentMs);
  37. consoleString += "[ TOTAL] ";
  38. consoleString += AZStd::string::format("%7.3f ms \n", totalMs);
  39. consoleString += "[SCRIPT COST] ";
  40. consoleString += AZStd::string::format("%7.4f%% of duration \n", stats.scriptCostPercent);
  41. return consoleString;
  42. }
  43. PerformanceStatistician::PerformanceStatistician()
  44. {
  45. PerformanceStatisticsEBus::Handler::BusConnect();
  46. }
  47. void PerformanceStatistician::ClearSnaphotStatistics()
  48. {
  49. m_executedScripts.clear();
  50. auto perfTracker = SystemComponent::ModPerformanceTracker();
  51. perfTracker->ClearGlobalReport();
  52. perfTracker->ClearSnapshotReport();
  53. }
  54. void PerformanceStatistician::ClearTrackingState()
  55. {
  56. m_trackingState = TrackingState::None;
  57. if (AZ::SystemTickBus::Handler::BusIsConnected())
  58. {
  59. AZ::SystemTickBus::Handler::BusDisconnect();
  60. }
  61. }
  62. void PerformanceStatistician::ConnectToSystemTickBus()
  63. {
  64. if (!AZ::SystemTickBus::Handler::BusIsConnected())
  65. {
  66. AZ::SystemTickBus::Handler::BusConnect();
  67. }
  68. }
  69. AZStd::vector<AZStd::string> PerformanceStatistician::GetExecutedScriptsSinceLastSnapshot() const
  70. {
  71. AZStd::vector<AZStd::string> scripts;
  72. scripts.reserve(m_executedScripts.size());
  73. for (auto& iter : m_executedScripts)
  74. {
  75. scripts.push_back(iter.second);
  76. }
  77. return scripts;
  78. }
  79. const PerformanceStatistics& PerformanceStatistician::GetStatistics() const
  80. {
  81. return m_accumulatedStats;
  82. }
  83. void PerformanceStatistician::OnStartTrackingRequested()
  84. {
  85. m_accumulatedStats.tickCount = 0;
  86. m_accumulatedStartTime = AZStd::chrono::steady_clock::now();
  87. }
  88. void PerformanceStatistician::OnSystemTick()
  89. {
  90. switch (m_trackingState)
  91. {
  92. case TrackingState::AccumulatedInProgress:
  93. UpdateTickCounts();
  94. break;
  95. case TrackingState::AccumulatedStartRequested:
  96. OnStartTrackingRequested();
  97. m_trackingState = TrackingState::AccumulatedInProgress;
  98. break;
  99. case TrackingState::AccumulatedStopRequested:
  100. UpdateAccumulatedTime();
  101. UpdateStatisticsFromTracker();
  102. UpdateAccumulatedStatistics();
  103. ClearTrackingState();
  104. break;
  105. case TrackingState::PerFrameInProgress:
  106. UpdateTickCounts();
  107. UpdateStatisticsFromTracker();
  108. break;
  109. case TrackingState::PerFrameStartRequested:
  110. OnStartTrackingRequested();
  111. m_trackingState = TrackingState::PerFrameInProgress;
  112. break;
  113. case TrackingState::PerFrameStopRequested:
  114. UpdateAccumulatedTime();
  115. UpdateStatisticsFromTracker();
  116. ClearTrackingState();
  117. break;
  118. default:
  119. break;
  120. }
  121. }
  122. void PerformanceStatistician::Reflect(AZ::ReflectContext* reflectContext)
  123. {
  124. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext))
  125. {
  126. behaviorContext->EBus<PerformanceStatisticsEBus>("PerformanceStatisticsEBus")
  127. ->Event("ClearSnaphotStatistics", &PerformanceStatisticsEBus::Events::ClearSnaphotStatistics)
  128. ->Event("TrackAccumulatedStart", &PerformanceStatisticsEBus::Events::TrackAccumulatedStart)
  129. ->Event("TrackAccumulatedStop", &PerformanceStatisticsEBus::Events::TrackAccumulatedStop)
  130. ->Event("TrackPerFrameStart", &PerformanceStatisticsEBus::Events::TrackPerFrameStart)
  131. ->Event("TrackPerFrameStop", &PerformanceStatisticsEBus::Events::TrackPerFrameStop)
  132. ;
  133. }
  134. }
  135. void PerformanceStatistician::TrackAccumulatedStart(AZ::s32 tickCount)
  136. {
  137. if (m_trackingState != TrackingState::AccumulatedStartRequested || m_accumulatedTickCountRemaining != tickCount)
  138. {
  139. m_trackingState = TrackingState::AccumulatedStartRequested;
  140. m_accumulatedTickCountRemaining = tickCount;
  141. ConnectToSystemTickBus();
  142. }
  143. }
  144. void PerformanceStatistician::TrackAccumulatedStop()
  145. {
  146. if (m_trackingState == TrackingState::AccumulatedInProgress)
  147. {
  148. m_trackingState = TrackingState::AccumulatedStopRequested;
  149. }
  150. }
  151. void PerformanceStatistician::TrackPerFrameStart()
  152. {
  153. if (m_trackingState != TrackingState::PerFrameInProgress)
  154. {
  155. m_trackingState = TrackingState::PerFrameStartRequested;
  156. ConnectToSystemTickBus();
  157. }
  158. }
  159. void PerformanceStatistician::TrackPerFrameStop()
  160. {
  161. if (m_trackingState == TrackingState::PerFrameInProgress || m_trackingState == TrackingState::AccumulatedStartRequested)
  162. {
  163. m_trackingState = TrackingState::PerFrameStopRequested;
  164. AZ::SystemTickBus::Handler::BusConnect();
  165. }
  166. }
  167. void PerformanceStatistician::UpdateAccumulatedStatistics()
  168. {
  169. m_accumulatedStats.report = SystemComponent::ModPerformanceTracker()->GetGlobalReportFull();
  170. m_accumulatedStats.CalculateSecondary();
  171. AZ_TracePrintf("ScriptCanvas", "Global Performance Report:\n%s", ToConsoleString(m_accumulatedStats).c_str());
  172. }
  173. void PerformanceStatistician::UpdateAccumulatedTime()
  174. {
  175. m_accumulatedStats.duration = AZStd::chrono::duration_cast<AZStd::chrono::microseconds>(AZStd::chrono::steady_clock::now() - m_accumulatedStartTime).count();
  176. }
  177. void PerformanceStatistician::UpdateStatisticsFromTracker()
  178. {
  179. auto perfTracker = SystemComponent::ModPerformanceTracker();
  180. perfTracker->CalculateReports();
  181. const PerformanceReport& snapShotReport = perfTracker->GetSnapshotReportFull();
  182. for (auto& snapshotIter : snapShotReport.byAsset)
  183. {
  184. auto iter = m_executedScripts.find(snapshotIter.first);
  185. if (iter == m_executedScripts.end())
  186. {
  187. AZ::Data::AssetInfo info;
  188. AZ::Data::AssetCatalogRequestBus::BroadcastResult(info, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, snapshotIter.first);
  189. if (info.m_assetType == azrtti_typeid<ScriptCanvas::RuntimeAsset>())
  190. {
  191. AZStd::string fileName;
  192. if (AZ::StringFunc::Path::GetFileName(info.m_relativePath.c_str(), fileName))
  193. {
  194. m_executedScripts.insert({ snapshotIter.first, fileName });
  195. }
  196. }
  197. }
  198. }
  199. }
  200. void PerformanceStatistician::UpdateTickCounts()
  201. {
  202. ++m_accumulatedStats.tickCount;
  203. --m_accumulatedTickCountRemaining;
  204. if (m_trackingState == TrackingState::AccumulatedInProgress && m_accumulatedTickCountRemaining == 0)
  205. {
  206. m_trackingState = TrackingState::AccumulatedStopRequested;
  207. }
  208. }
  209. }
  210. }