Integrating latest 47acbe8
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <ScriptCanvas/Asset/RuntimeAsset.h>
|
||||
#include <ScriptCanvas/Execution/ExecutionBus.h>
|
||||
#include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h>
|
||||
#include <ScriptCanvas/PerformanceStatistician.h>
|
||||
#include <ScriptCanvas/PerformanceTracker.h>
|
||||
#include <ScriptCanvas/SystemComponent.h>
|
||||
|
||||
namespace ScriptCanvas
|
||||
{
|
||||
namespace Execution
|
||||
{
|
||||
void PerformanceStatistics::CalculateSecondary()
|
||||
{
|
||||
scriptCostPercent = aznumeric_cast<double>(report.tracking.timing.totalTime) / aznumeric_cast<double>(duration);
|
||||
}
|
||||
|
||||
AZStd::string ToConsoleString(const PerformanceStatistics& stats)
|
||||
{
|
||||
AZStd::string consoleString("\n");
|
||||
|
||||
const double initializingMs = aznumeric_caster(stats.report.tracking.timing.initializationTime / 1000.0);
|
||||
const double executionMs = aznumeric_caster(stats.report.tracking.timing.executionTime / 1000.0);
|
||||
const double latentMs = aznumeric_caster(stats.report.tracking.timing.latentTime / 1000.0);
|
||||
const double totalMs = aznumeric_caster(stats.report.tracking.timing.totalTime / 1000.0);
|
||||
|
||||
consoleString += "[ INITIALIZE] ";
|
||||
consoleString += AZStd::string::format("%7.3f ms \n", initializingMs);
|
||||
|
||||
consoleString += "[ EXECUTION] ";
|
||||
consoleString += AZStd::string::format("%7.3f ms \n", executionMs);
|
||||
|
||||
consoleString += "[ LATENT] ";
|
||||
consoleString += AZStd::string::format("%7.3f ms \n", latentMs);
|
||||
|
||||
consoleString += "[ TOTAL] ";
|
||||
consoleString += AZStd::string::format("%7.3f ms \n", totalMs);
|
||||
|
||||
consoleString += "[SCRIPT COST] ";
|
||||
consoleString += AZStd::string::format("%7.4f%% of duration \n", stats.scriptCostPercent);
|
||||
|
||||
return consoleString;
|
||||
}
|
||||
|
||||
PerformanceStatistician::PerformanceStatistician()
|
||||
{
|
||||
PerformanceStatisticsEBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void PerformanceStatistician::ClearSnaphotStatistics()
|
||||
{
|
||||
m_executedScripts.clear();
|
||||
|
||||
auto perfTracker = SystemComponent::ModPerformanceTracker();
|
||||
perfTracker->ClearGlobalReport();
|
||||
perfTracker->ClearSnapshotReport();
|
||||
}
|
||||
|
||||
void PerformanceStatistician::ClearTrackingState()
|
||||
{
|
||||
m_trackingState = TrackingState::None;
|
||||
|
||||
if (AZ::SystemTickBus::Handler::BusIsConnected())
|
||||
{
|
||||
AZ::SystemTickBus::Handler::BusDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceStatistician::ConnectToSystemTickBus()
|
||||
{
|
||||
if (!AZ::SystemTickBus::Handler::BusIsConnected())
|
||||
{
|
||||
AZ::SystemTickBus::Handler::BusConnect();
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::string> PerformanceStatistician::GetExecutedScriptsSinceLastSnapshot() const
|
||||
{
|
||||
AZStd::vector<AZStd::string> scripts;
|
||||
scripts.reserve(m_executedScripts.size());
|
||||
|
||||
for (auto& iter : m_executedScripts)
|
||||
{
|
||||
scripts.push_back(iter.second);
|
||||
}
|
||||
|
||||
return scripts;
|
||||
}
|
||||
|
||||
const PerformanceStatistics& PerformanceStatistician::GetStatistics() const
|
||||
{
|
||||
return m_accumulatedStats;
|
||||
}
|
||||
|
||||
void PerformanceStatistician::OnStartTrackingRequested()
|
||||
{
|
||||
m_accumulatedStats.tickCount = 0;
|
||||
m_accumulatedTickCountRemaining;
|
||||
m_accumulatedStartTime = AZStd::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
void PerformanceStatistician::OnSystemTick()
|
||||
{
|
||||
switch (m_trackingState)
|
||||
{
|
||||
case TrackingState::AccumulatedInProgress:
|
||||
UpdateTickCounts();
|
||||
break;
|
||||
|
||||
case TrackingState::AccumulatedStartRequested:
|
||||
OnStartTrackingRequested();
|
||||
m_trackingState = TrackingState::AccumulatedInProgress;
|
||||
break;
|
||||
|
||||
case TrackingState::AccumulatedStopRequested:
|
||||
UpdateAccumulatedTime();
|
||||
UpdateStatisticsFromTracker();
|
||||
UpdateAccumulatedStatistics();
|
||||
ClearTrackingState();
|
||||
break;
|
||||
|
||||
case TrackingState::PerFrameInProgress:
|
||||
UpdateTickCounts();
|
||||
UpdateStatisticsFromTracker();
|
||||
break;
|
||||
|
||||
case TrackingState::PerFrameStartRequested:
|
||||
OnStartTrackingRequested();
|
||||
m_trackingState = TrackingState::PerFrameInProgress;
|
||||
break;
|
||||
|
||||
case TrackingState::PerFrameStopRequested:
|
||||
UpdateAccumulatedTime();
|
||||
UpdateStatisticsFromTracker();
|
||||
ClearTrackingState();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceStatistician::Reflect(AZ::ReflectContext* reflectContext)
|
||||
{
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(reflectContext))
|
||||
{
|
||||
behaviorContext->EBus<PerformanceStatisticsEBus>("PerformanceStatisticsEBus")
|
||||
->Event("ClearSnaphotStatistics", &PerformanceStatisticsEBus::Events::ClearSnaphotStatistics)
|
||||
->Event("TrackAccumulatedStart", &PerformanceStatisticsEBus::Events::TrackAccumulatedStart)
|
||||
->Event("TrackAccumulatedStop", &PerformanceStatisticsEBus::Events::TrackAccumulatedStop)
|
||||
->Event("TrackPerFrameStart", &PerformanceStatisticsEBus::Events::TrackPerFrameStart)
|
||||
->Event("TrackPerFrameStop", &PerformanceStatisticsEBus::Events::TrackPerFrameStop)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceStatistician::TrackAccumulatedStart(AZ::s32 tickCount)
|
||||
{
|
||||
if (m_trackingState != TrackingState::AccumulatedStartRequested || m_accumulatedTickCountRemaining != tickCount)
|
||||
{
|
||||
m_trackingState = TrackingState::AccumulatedStartRequested;
|
||||
m_accumulatedTickCountRemaining = tickCount;
|
||||
ConnectToSystemTickBus();
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceStatistician::TrackAccumulatedStop()
|
||||
{
|
||||
if (m_trackingState == TrackingState::AccumulatedInProgress)
|
||||
{
|
||||
m_trackingState = TrackingState::AccumulatedStopRequested;
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceStatistician::TrackPerFrameStart()
|
||||
{
|
||||
if (m_trackingState != TrackingState::PerFrameInProgress)
|
||||
{
|
||||
m_trackingState = TrackingState::PerFrameStartRequested;
|
||||
ConnectToSystemTickBus();
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceStatistician::TrackPerFrameStop()
|
||||
{
|
||||
if (m_trackingState == TrackingState::PerFrameInProgress || m_trackingState == TrackingState::AccumulatedStartRequested)
|
||||
{
|
||||
m_trackingState = TrackingState::PerFrameStopRequested;
|
||||
AZ::SystemTickBus::Handler::BusConnect();
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceStatistician::UpdateAccumulatedStatistics()
|
||||
{
|
||||
m_accumulatedStats.report = SystemComponent::ModPerformanceTracker()->GetGlobalReportFull();
|
||||
m_accumulatedStats.CalculateSecondary();
|
||||
AZ_TracePrintf("ScriptCanvas", "Global Performance Report:\n%s", ToConsoleString(m_accumulatedStats).c_str());
|
||||
}
|
||||
|
||||
void PerformanceStatistician::UpdateAccumulatedTime()
|
||||
{
|
||||
m_accumulatedStats.duration = AZStd::chrono::microseconds(AZStd::chrono::system_clock::now() - m_accumulatedStartTime).count();
|
||||
}
|
||||
|
||||
void PerformanceStatistician::UpdateStatisticsFromTracker()
|
||||
{
|
||||
auto perfTracker = SystemComponent::ModPerformanceTracker();
|
||||
perfTracker->CalculateReports();
|
||||
const PerformanceReport& snapShotReport = perfTracker->GetSnapshotReportFull();
|
||||
|
||||
for (auto& snapshotIter : snapShotReport.byAsset)
|
||||
{
|
||||
auto iter = m_executedScripts.find(snapshotIter.first);
|
||||
if (iter == m_executedScripts.end())
|
||||
{
|
||||
AZ::Data::AssetInfo info;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(info, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, snapshotIter.first);
|
||||
if (info.m_assetType == azrtti_typeid<ScriptCanvas::RuntimeAsset>())
|
||||
{
|
||||
AZStd::string fileName;
|
||||
if (AZ::StringFunc::Path::GetFileName(info.m_relativePath.c_str(), fileName))
|
||||
{
|
||||
m_executedScripts.insert({ snapshotIter.first, fileName });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceStatistician::UpdateTickCounts()
|
||||
{
|
||||
++m_accumulatedStats.tickCount;
|
||||
--m_accumulatedTickCountRemaining;
|
||||
|
||||
if (m_trackingState == TrackingState::AccumulatedInProgress && m_accumulatedTickCountRemaining == 0)
|
||||
{
|
||||
m_trackingState = TrackingState::AccumulatedStopRequested;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h>
|
||||
|
||||
#include <ScriptCanvas/PerformanceTracker.h>
|
||||
|
||||
namespace ScriptCanvas
|
||||
{
|
||||
namespace Execution
|
||||
{
|
||||
PerformanceTracker::PerformanceTracker()
|
||||
{}
|
||||
|
||||
PerformanceTracker::~PerformanceTracker()
|
||||
{
|
||||
AZStd::lock_guard lock(m_activeTimerMutex);
|
||||
|
||||
for (auto iter : m_activeTimers)
|
||||
{
|
||||
delete iter.second;
|
||||
}
|
||||
m_activeTimers.clear();
|
||||
|
||||
for (auto iter : m_timersByAsset)
|
||||
{
|
||||
delete iter.second;
|
||||
}
|
||||
m_timersByAsset.clear();
|
||||
}
|
||||
|
||||
void PerformanceTracker::CalculateReports()
|
||||
{
|
||||
AZStd::lock_guard lock(m_activeTimerMutex);
|
||||
|
||||
m_snapshotReport.tracking.activationCount += aznumeric_cast<AZ::u32>(m_activeTimers.size());
|
||||
m_globalReport.tracking.activationCount += aznumeric_cast<AZ::u32>(m_activeTimers.size());
|
||||
|
||||
for (auto& iter : m_activeTimers)
|
||||
{
|
||||
const auto report = iter.second->GetReport();
|
||||
m_snapshotReport.tracking.timing += report;
|
||||
m_globalReport.tracking.timing += report;
|
||||
delete iter.second;
|
||||
}
|
||||
|
||||
m_activeTimers.clear();
|
||||
|
||||
for (auto& iter : m_timersByAsset)
|
||||
{
|
||||
const auto report = iter.second->timer.GetReport();
|
||||
auto& snapshotByAssetReport = *ModOrCreateReport(m_snapshotReport.byAsset, iter.first);
|
||||
auto& globalByAssetReport = *ModOrCreateReport(m_globalReport.byAsset, iter.first);
|
||||
snapshotByAssetReport.timing += report;
|
||||
snapshotByAssetReport.activationCount += iter.second->assetActivationCount;
|
||||
globalByAssetReport.timing += report;
|
||||
globalByAssetReport.activationCount += iter.second->assetActivationCount;
|
||||
delete iter.second;
|
||||
}
|
||||
|
||||
m_timersByAsset.clear();
|
||||
|
||||
m_lastCapturedSnapshot = m_snapshotReport;
|
||||
m_lastCapturedGlobal = m_globalReport;
|
||||
m_snapshotReport = {};
|
||||
}
|
||||
|
||||
void PerformanceTracker::ClearGlobalReport()
|
||||
{
|
||||
AZStd::lock_guard lock(m_activeTimerMutex);
|
||||
m_globalReport = {};
|
||||
}
|
||||
|
||||
void PerformanceTracker::ClearSnapshotReport()
|
||||
{
|
||||
AZStd::lock_guard lock(m_activeTimerMutex);
|
||||
m_snapshotReport = {};
|
||||
}
|
||||
|
||||
PerformanceTimer* PerformanceTracker::CreateTimer(PerformanceKey key)
|
||||
{
|
||||
AZStd::lock_guard lock(m_activeTimerMutex);
|
||||
return m_activeTimers.insert({ key, aznew PerformanceTimer() }).first->second;
|
||||
}
|
||||
|
||||
void PerformanceTracker::FinalizeReport(PerformanceKey key, const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
AZStd::lock_guard lock(m_activeTimerMutex);
|
||||
|
||||
auto iter = m_activeTimers.find(key);
|
||||
if (iter != m_activeTimers.end())
|
||||
{
|
||||
PerformanceTimer* timer = iter->second;
|
||||
auto report = timer->GetReport();
|
||||
auto& globalByAssetReport = *ModOrCreateReport(m_globalReport.byAsset, assetId);
|
||||
auto& snapshotByAssetReport = *ModOrCreateReport(m_snapshotReport.byAsset, assetId);
|
||||
snapshotByAssetReport.timing += report;
|
||||
globalByAssetReport.timing += report;
|
||||
m_snapshotReport.tracking.timing += report;
|
||||
m_globalReport.tracking.timing += report;
|
||||
m_activeTimers.erase(iter);
|
||||
delete timer;
|
||||
}
|
||||
}
|
||||
|
||||
PerformanceTracker::AssetTimer* PerformanceTracker::GetOrCreateTimer(const AZ::Data::AssetId& key)
|
||||
{
|
||||
AZStd::lock_guard lock(m_activeTimerMutex);
|
||||
auto iter = m_timersByAsset.find(key);
|
||||
|
||||
if (iter != m_timersByAsset.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_timersByAsset.insert({ key, aznew PerformanceTracker::AssetTimer() }).first->second;
|
||||
}
|
||||
}
|
||||
|
||||
PerformanceTimer* PerformanceTracker::GetOrCreateTimer(PerformanceKey key)
|
||||
{
|
||||
AZStd::lock_guard lock(m_activeTimerMutex);
|
||||
auto iter = m_activeTimers.find(key);
|
||||
|
||||
if (iter != m_activeTimers.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_activeTimers.insert({ key, aznew PerformanceTimer() }).first->second;
|
||||
}
|
||||
}
|
||||
|
||||
PerformanceTrackingReport PerformanceTracker::GetGlobalReport() const
|
||||
{
|
||||
return m_lastCapturedGlobal.tracking;
|
||||
}
|
||||
|
||||
PerformanceTrackingReport PerformanceTracker::GetGlobalReportByAsset(const AZ::Data::AssetId& assetId) const
|
||||
{
|
||||
return GetReportByAsset(m_lastCapturedGlobal.byAsset, assetId);
|
||||
}
|
||||
|
||||
const PerformanceReport& PerformanceTracker::GetGlobalReportFull() const
|
||||
{
|
||||
return m_globalReport;
|
||||
}
|
||||
|
||||
PerformanceTrackingReport PerformanceTracker::GetReportByAsset(const PerformanceReportByAsset& reports, AZ::Data::AssetId key)
|
||||
{
|
||||
auto iter = reports.find(key);
|
||||
return iter != reports.end() ? iter->second : PerformanceTrackingReport{};
|
||||
}
|
||||
|
||||
PerformanceTrackingReport PerformanceTracker::GetSnapshotReport() const
|
||||
{
|
||||
return m_lastCapturedSnapshot.tracking;
|
||||
}
|
||||
|
||||
PerformanceTrackingReport PerformanceTracker::GetSnapshotReportByAsset(const AZ::Data::AssetId& assetId) const
|
||||
{
|
||||
return GetReportByAsset(m_lastCapturedSnapshot.byAsset, assetId);
|
||||
}
|
||||
|
||||
const PerformanceReport& PerformanceTracker::GetSnapshotReportFull() const
|
||||
{
|
||||
return m_lastCapturedSnapshot;
|
||||
}
|
||||
|
||||
PerformanceTrackingReport* PerformanceTracker::ModOrCreateReport(PerformanceReportByAsset& reports, AZ::Data::AssetId key)
|
||||
{
|
||||
auto iter = reports.find(key);
|
||||
|
||||
if (iter != reports.end())
|
||||
{
|
||||
return &iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &reports.insert({ key, PerformanceTrackingReport() }).first->second;
|
||||
}
|
||||
}
|
||||
|
||||
void PerformanceTracker::ReportExecutionTime(PerformanceKey key, const AZ::Data::AssetId& assetId, AZStd::sys_time_t time)
|
||||
{
|
||||
GetOrCreateTimer(key)->AddExecutionTime(time);
|
||||
GetOrCreateTimer(assetId)->timer.AddExecutionTime(time);
|
||||
}
|
||||
|
||||
void PerformanceTracker::ReportLatentTime(PerformanceKey key, const AZ::Data::AssetId& assetId, AZStd::sys_time_t time)
|
||||
{
|
||||
GetOrCreateTimer(key)->AddLatentTime(time);
|
||||
GetOrCreateTimer(assetId)->timer.AddLatentTime(time);
|
||||
}
|
||||
|
||||
void PerformanceTracker::ReportInitializationTime(PerformanceKey key, const AZ::Data::AssetId& assetId, AZStd::sys_time_t time)
|
||||
{
|
||||
CreateTimer(key)->AddInitializationTime(time);
|
||||
AssetTimer* assetTimer = GetOrCreateTimer(assetId);
|
||||
assetTimer->timer.AddInitializationTime(time);
|
||||
++(assetTimer->assetActivationCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ namespace ScriptCanvas
|
||||
ScriptCanvas::Node::CreateDescriptor(),
|
||||
ScriptCanvas::Debugger::ServiceComponent::CreateDescriptor(),
|
||||
ScriptCanvas::Graph::CreateDescriptor(),
|
||||
ScriptCanvas::ScriptCanvasFunctionDataComponent::CreateDescriptor(),
|
||||
ScriptCanvasEditor::ScriptCanvasFunctionDataComponent::CreateDescriptor(),
|
||||
ScriptCanvas::PureData::CreateDescriptor(),
|
||||
ScriptCanvas::GraphVariableManagerComponent::CreateDescriptor(),
|
||||
ScriptCanvas::RuntimeComponent::CreateDescriptor(),
|
||||
@@ -79,4 +79,4 @@ namespace ScriptCanvas
|
||||
azrtti_typeid<ScriptCanvas::Debugger::ServiceComponent>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,6 @@ namespace ScriptCanvas
|
||||
}
|
||||
}
|
||||
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_ScriptCanvasGem, ScriptCanvas::ScriptCanvasModule)
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_ScriptCanvas, ScriptCanvas::ScriptCanvasModule)
|
||||
|
||||
#endif // !SCRIPTCANVAS_EDITOR
|
||||
@@ -10,27 +10,40 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <AzCore/Component/EntityUtils.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
|
||||
#include <Libraries/Libraries.h>
|
||||
#include <ScriptCanvas/Core/Node.h>
|
||||
#include <ScriptCanvas/Core/Contract.h>
|
||||
#include <ScriptCanvas/Core/Slot.h>
|
||||
#include <ScriptCanvas/Core/Graph.h>
|
||||
#include <ScriptCanvas/Core/Node.h>
|
||||
#include <ScriptCanvas/Core/Nodeable.h>
|
||||
#include <ScriptCanvas/Core/Slot.h>
|
||||
#include <ScriptCanvas/Data/DataRegistry.h>
|
||||
#include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h>
|
||||
#include <ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.h>
|
||||
#include <ScriptCanvas/Execution/RuntimeComponent.h>
|
||||
#include <ScriptCanvas/Variable/GraphVariableManagerComponent.h>
|
||||
#include <ScriptCanvas/SystemComponent.h>
|
||||
#include <ScriptCanvas/Variable/GraphVariableManagerComponent.h>
|
||||
|
||||
#if defined(SC_EXECUTION_TRACE_ENABLED)
|
||||
#include <ScriptCanvas/Asset/ExecutionLogAsset.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
namespace ScriptCanvasSystemComponentCpp
|
||||
{
|
||||
#if !defined(_RELEASE) && !defined(PERFORMANCE_BUILD)
|
||||
const int k_infiniteLoopDetectionMaxIterations = 3000;
|
||||
const int k_maxHandlerStackDepth = 25;
|
||||
#else
|
||||
const int k_infiniteLoopDetectionMaxIterations = 10000;
|
||||
const int k_maxHandlerStackDepth = 100;
|
||||
#endif
|
||||
|
||||
bool IsDeprecated(const AZ::AttributeArray& attributes)
|
||||
{
|
||||
bool isDeprecated{};
|
||||
@@ -42,13 +55,14 @@ namespace
|
||||
|
||||
return isDeprecated;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ScriptCanvas
|
||||
{
|
||||
|
||||
void SystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
Nodeable::Reflect(context);
|
||||
ReflectLibraries(context);
|
||||
|
||||
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
@@ -58,6 +72,7 @@ namespace ScriptCanvas
|
||||
// ScriptCanvas avoids a use dependency on the AssetBuilderSDK. Therefore the Crc is used directly to register this component with the Gem builder
|
||||
->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AZ_CRC("AssetBuilder", 0xc739c7d7) }))
|
||||
->Field("m_infiniteLoopDetectionMaxIterations", &SystemComponent::m_infiniteLoopDetectionMaxIterations)
|
||||
->Field("maxHandlerStackDepth", &SystemComponent::m_maxHandlerStackDepth)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* ec = serialize->GetEditContext())
|
||||
@@ -68,6 +83,8 @@ namespace ScriptCanvas
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SystemComponent::m_infiniteLoopDetectionMaxIterations, "Infinite Loop Protection Max Iterations", "Script Canvas will avoid infinite loops by detecting potentially re-entrant conditions that execute up to this number of iterations.")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &SystemComponent::m_maxHandlerStackDepth, "Max Handler Stack Depth", "Script Canvas will avoid infinite loops at run-time by detecting sending Ebus Events while handling said Events. This limits the stack depth of the broadcast.")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 1000) // Safeguard user given value is valid
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -91,6 +108,9 @@ namespace ScriptCanvas
|
||||
|
||||
void SystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
// \todo configure the application to require these services
|
||||
// required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601));
|
||||
// required.push_back(AZ_CRC("ScriptService", 0x787235ab));
|
||||
}
|
||||
|
||||
void SystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
@@ -100,6 +120,9 @@ namespace ScriptCanvas
|
||||
void SystemComponent::Init()
|
||||
{
|
||||
RegisterCreatableTypes();
|
||||
|
||||
m_infiniteLoopDetectionMaxIterations = ScriptCanvasSystemComponentCpp::k_infiniteLoopDetectionMaxIterations;
|
||||
m_maxHandlerStackDepth = ScriptCanvasSystemComponentCpp::k_maxHandlerStackDepth;
|
||||
}
|
||||
|
||||
void SystemComponent::Activate()
|
||||
@@ -111,12 +134,50 @@ namespace ScriptCanvas
|
||||
{
|
||||
AZ::BehaviorContextBus::Handler::BusConnect(behaviorContext);
|
||||
}
|
||||
|
||||
if (IsAnyScriptInterpreted()) // or if is the editor...
|
||||
{
|
||||
Execution::ActivateInterpreted();
|
||||
}
|
||||
|
||||
SafeRegisterPerformanceTracker();
|
||||
}
|
||||
|
||||
void SystemComponent::Deactivate()
|
||||
{
|
||||
AZ::BehaviorContextBus::Handler::BusDisconnect();
|
||||
SystemRequestBus::Handler::BusDisconnect();
|
||||
|
||||
ModPerformanceTracker()->CalculateReports();
|
||||
Execution::PerformanceTrackingReport report = ModPerformanceTracker()->GetGlobalReport();
|
||||
|
||||
const double ready = aznumeric_caster(report.timing.initializationTime);
|
||||
const double instant = aznumeric_caster(report.timing.executionTime);
|
||||
const double latent = aznumeric_caster(report.timing.latentTime);
|
||||
const double total = aznumeric_caster(report.timing.totalTime);
|
||||
|
||||
std::cerr << "Global ScriptCanvas Performance Report:\n";
|
||||
std::cerr << "[ INITIALIZE] " << AZStd::string::format("%7.3f ms \n", ready / 1000.0).c_str();
|
||||
std::cerr << "[ EXECUTION] " << AZStd::string::format("%7.3f ms \n", instant / 1000.0).c_str();
|
||||
std::cerr << "[ LATENT] " << AZStd::string::format("%7.3f ms \n", latent / 1000.0).c_str();
|
||||
std::cerr << "[ TOTAL] " << AZStd::string::format("%7.3f ms \n", total / 1000.0).c_str();
|
||||
|
||||
SafeUnregisterPerformanceTracker();
|
||||
}
|
||||
|
||||
bool SystemComponent::IsScriptUnitTestingInProgress()
|
||||
{
|
||||
return m_scriptBasedUnitTestingInProgress;
|
||||
}
|
||||
|
||||
void SystemComponent::MarkScriptUnitTestBegin()
|
||||
{
|
||||
m_scriptBasedUnitTestingInProgress = true;
|
||||
}
|
||||
|
||||
void SystemComponent::MarkScriptUnitTestEnd()
|
||||
{
|
||||
m_scriptBasedUnitTestingInProgress = false;
|
||||
}
|
||||
|
||||
void SystemComponent::CreateEngineComponentsOnEntity(AZ::Entity* entity)
|
||||
@@ -249,7 +310,7 @@ namespace ScriptCanvas
|
||||
|
||||
canCreate = listOnly || (!excludeClassAttributeData || (!(flags & exclusionFlags)));
|
||||
canCreate = canCreate && (serializeContext->FindClassData(behaviorClass->m_typeId));
|
||||
canCreate = canCreate && !IsDeprecated(behaviorClass->m_attributes);
|
||||
canCreate = canCreate && !ScriptCanvasSystemComponentCpp::IsDeprecated(behaviorClass->m_attributes);
|
||||
|
||||
if (AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes))
|
||||
{
|
||||
@@ -291,7 +352,7 @@ namespace ScriptCanvas
|
||||
auto excludeClassAttributeData = azrtti_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes));
|
||||
bool canCreate = !excludeClassAttributeData || !(excludeClassAttributeData->Get(nullptr) & exclusionFlags);
|
||||
canCreate = canCreate && (serializeContext->FindClassData(behaviorClass->m_typeId) || AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes));
|
||||
canCreate = canCreate && !IsDeprecated(behaviorClass->m_attributes);
|
||||
canCreate = canCreate && !ScriptCanvasSystemComponentCpp::IsDeprecated(behaviorClass->m_attributes);
|
||||
|
||||
// create able variables must have full memory support
|
||||
canCreate = canCreate &&
|
||||
@@ -317,4 +378,59 @@ namespace ScriptCanvas
|
||||
dataRegistry->UnregisterType(behaviorClass->m_typeId);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemComponent::SetInterpretedBuildConfiguration(BuildConfiguration config)
|
||||
{
|
||||
Execution::SetInterpretedExecutionMode(config);
|
||||
}
|
||||
|
||||
AZ::EnvironmentVariable<Execution::PerformanceTracker*> SystemComponent::s_perfTracker;
|
||||
AZStd::shared_mutex SystemComponent::s_perfTrackerMutex;
|
||||
|
||||
Execution::PerformanceTracker* SystemComponent::ModPerformanceTracker()
|
||||
{
|
||||
// First attempt to use the module-static reference; take a read lock to check it.
|
||||
// This is the fast path which won't block.
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(s_perfTrackerMutex);
|
||||
if (s_perfTracker)
|
||||
{
|
||||
return s_perfTracker.Get();
|
||||
}
|
||||
}
|
||||
|
||||
// If the instance doesn't exist (which means we could be in a different module),
|
||||
// take the full lock and request it.
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(s_perfTrackerMutex);
|
||||
s_perfTracker = AZ::Environment::FindVariable<Execution::PerformanceTracker*>(s_trackerName);
|
||||
return s_perfTracker ? s_perfTracker.Get() : nullptr;
|
||||
}
|
||||
|
||||
void SystemComponent::SafeRegisterPerformanceTracker()
|
||||
{
|
||||
if (ModPerformanceTracker())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(s_perfTrackerMutex);
|
||||
|
||||
auto tracker = aznew Execution::PerformanceTracker();
|
||||
s_perfTracker = AZ::Environment::CreateVariable<Execution::PerformanceTracker*>(s_trackerName);
|
||||
s_perfTracker.Get() = tracker;
|
||||
}
|
||||
|
||||
void SystemComponent::SafeUnregisterPerformanceTracker()
|
||||
{
|
||||
auto performanceTracker = ModPerformanceTracker();
|
||||
if (!performanceTracker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(s_perfTrackerMutex);
|
||||
*s_perfTracker = nullptr;
|
||||
s_perfTracker.Reset();
|
||||
delete performanceTracker;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user