Refactoring to use AZ::Events

Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com>
This commit is contained in:
AMZN-Olex
2021-07-28 09:53:44 -04:00
parent 5ebb096d1a
commit 462c31b5de
11 changed files with 156 additions and 133 deletions
@@ -14,7 +14,7 @@
#pragma optimize("", off)
namespace MultiplayerDiagnostics
namespace Multiplayer
{
void MultiplayerDebugByteReporter::ReportBytes(size_t byteSize)
{
@@ -44,7 +44,7 @@ namespace MultiplayerDiagnostics
return 0.0f;
}
return (1.0f * m_totalBytes) / m_count;
return aznumeric_cast<float>(m_totalBytes) / aznumeric_cast<float>(m_count);
}
size_t MultiplayerDebugByteReporter::GetMaxBytes() const
@@ -64,26 +64,26 @@ namespace MultiplayerDiagnostics
float MultiplayerDebugByteReporter::GetKbitsPerSecond()
{
auto now = AZStd::chrono::monotonic_clock::now();
const auto now = AZStd::chrono::monotonic_clock::now();
// Check the amount of time elapsed and update totals if necessary.
// Time here is measured in whole seconds from the epoch, providing synchronization in
// reporting intervals across all byte reporters.
AZStd::chrono::seconds nowSeconds = AZStd::chrono::duration_cast<AZStd::chrono::seconds>(now.time_since_epoch());
AZStd::chrono::seconds secondsSinceLastUpdate = nowSeconds -
const AZStd::chrono::seconds nowSeconds = AZStd::chrono::duration_cast<AZStd::chrono::seconds>(now.time_since_epoch());
const AZStd::chrono::seconds secondsSinceLastUpdate = nowSeconds -
AZStd::chrono::duration_cast<AZStd::chrono::seconds>(m_lastUpdateTime.time_since_epoch());
if (secondsSinceLastUpdate.count())
{
// normalize over elapsed milliseconds
const int k_millisecondsPerSecond = 1000;
auto msSinceLastUpdate = AZStd::chrono::duration_cast<AZStd::chrono::milliseconds>(now - m_lastUpdateTime);
m_totalBytesLastSecond = k_millisecondsPerSecond * (1.f * m_totalBytesThisSecond / msSinceLastUpdate.count());
constexpr int k_millisecondsPerSecond = 1000;
const auto msSinceLastUpdate = AZStd::chrono::duration_cast<AZStd::chrono::milliseconds>(now - m_lastUpdateTime);
m_totalBytesLastSecond = k_millisecondsPerSecond * aznumeric_cast<float>(m_totalBytesThisSecond) / aznumeric_cast<float>(msSinceLastUpdate.count());
m_totalBytesThisSecond = 0;
m_lastUpdateTime = now;
}
const float k_bitsPerByte = 8.0f;
const int k_bitsPerKilobit = 1024;
constexpr float k_bitsPerByte = 8.0f;
constexpr int k_bitsPerKilobit = 1024;
return k_bitsPerByte * m_totalBytesLastSecond / k_bitsPerKilobit;
}
@@ -107,19 +107,19 @@ namespace MultiplayerDiagnostics
m_aggregateBytes = 0;
}
void ComponentReporter::ReportField(const char* fieldName, size_t byteSize)
void MultiplayerDebugComponentReporter::ReportField(const char* fieldName, size_t byteSize)
{
MultiplayerDebugByteReporter::AggregateBytes(byteSize);
m_fieldReports[fieldName].ReportBytes(byteSize);
}
void ComponentReporter::ReportFragmentEnd()
void MultiplayerDebugComponentReporter::ReportFragmentEnd()
{
MultiplayerDebugByteReporter::ReportAggregateBytes();
m_componentDirtyBytes.ReportAggregateBytes();
}
AZStd::vector<ComponentReporter::Report> ComponentReporter::GetFieldReports()
AZStd::vector<MultiplayerDebugComponentReporter::Report> MultiplayerDebugComponentReporter::GetFieldReports()
{
AZStd::vector<Report> copy;
for (auto field = m_fieldReports.begin(); field != m_fieldReports.end(); ++field)
@@ -137,7 +137,7 @@ namespace MultiplayerDiagnostics
return copy;
}
void ComponentReporter::Combine(const ComponentReporter& other)
void MultiplayerDebugComponentReporter::Combine(const MultiplayerDebugComponentReporter& other)
{
MultiplayerDebugByteReporter::Combine(other);
@@ -149,7 +149,7 @@ namespace MultiplayerDiagnostics
m_componentDirtyBytes.Combine(other.m_componentDirtyBytes);
}
void EntityReporter::ReportField(AZ::u32 index, const char* componentName,
void MultiplayerDebugEntityReporter::ReportField(AZ::u32 index, const char* componentName,
const char* fieldName, size_t byteSize)
{
if (m_currentComponentReport == nullptr)
@@ -163,7 +163,7 @@ namespace MultiplayerDiagnostics
MultiplayerDebugByteReporter::AggregateBytes(byteSize);
}
void EntityReporter::ReportFragmentEnd()
void MultiplayerDebugEntityReporter::ReportFragmentEnd()
{
if (m_currentComponentReport)
{
@@ -175,7 +175,7 @@ namespace MultiplayerDiagnostics
MultiplayerDebugByteReporter::ReportAggregateBytes();
}
void EntityReporter::Combine(const EntityReporter& other)
void MultiplayerDebugEntityReporter::Combine(const MultiplayerDebugEntityReporter& other)
{
MultiplayerDebugByteReporter::Combine(other);
@@ -188,7 +188,7 @@ namespace MultiplayerDiagnostics
m_gdeDirtyBytes.Combine(other.m_gdeDirtyBytes);
}
void EntityReporter::Reset()
void MultiplayerDebugEntityReporter::Reset()
{
MultiplayerDebugByteReporter::Reset();
@@ -196,7 +196,7 @@ namespace MultiplayerDiagnostics
m_gdeDirtyBytes.Reset();
}
AZStd::map<AZStd::string, ComponentReporter>& EntityReporter::GetComponentReports()
AZStd::map<AZStd::string, MultiplayerDebugComponentReporter>& MultiplayerDebugEntityReporter::GetComponentReports()
{
return m_componentReports;
}
@@ -13,7 +13,7 @@
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
namespace MultiplayerDiagnostics
namespace Multiplayer
{
class MultiplayerDebugByteReporter
{
@@ -48,10 +48,10 @@ namespace MultiplayerDiagnostics
AZStd::chrono::monotonic_clock::time_point m_lastUpdateTime;
};
class ComponentReporter : public MultiplayerDebugByteReporter
class MultiplayerDebugComponentReporter : public MultiplayerDebugByteReporter
{
public:
ComponentReporter() = default;
MultiplayerDebugComponentReporter() = default;
void ReportField(const char* fieldName, size_t byteSize);
void ReportFragmentEnd();
@@ -61,22 +61,22 @@ namespace MultiplayerDiagnostics
AZStd::size_t GetTotalDirtyBits() const { return m_componentDirtyBytes.GetTotalBytes(); }
float GetAvgDirtyBits() const { return m_componentDirtyBytes.GetAverageBytes(); }
void Combine(const ComponentReporter& other);
void Combine(const MultiplayerDebugComponentReporter& other);
private:
AZStd::map<AZStd::string, MultiplayerDebugByteReporter> m_fieldReports;
MultiplayerDebugByteReporter m_componentDirtyBytes;
};
class EntityReporter : public MultiplayerDebugByteReporter
class MultiplayerDebugEntityReporter : public MultiplayerDebugByteReporter
{
public:
EntityReporter() = default;
MultiplayerDebugEntityReporter() = default;
void ReportField(AZ::u32 index, const char* componentName, const char* fieldName, size_t byteSize);
void ReportFragmentEnd();
void Combine(const EntityReporter& other);
void Combine(const MultiplayerDebugEntityReporter& other);
void Reset() override;
const char* GetEntityName() const { return m_entityName.c_str(); }
@@ -86,13 +86,13 @@ namespace MultiplayerDiagnostics
m_entityName = entityName;
}
AZStd::map<AZStd::string, ComponentReporter>& GetComponentReports();
AZStd::map<AZStd::string, MultiplayerDebugComponentReporter>& GetComponentReports();
AZStd::size_t GetTotalDirtyBits() const { return m_gdeDirtyBytes.GetTotalBytes(); }
float GetAvgDirtyBits() const { return m_gdeDirtyBytes.GetAverageBytes(); }
private:
ComponentReporter* m_currentComponentReport = nullptr;
AZStd::map<AZStd::string, ComponentReporter> m_componentReports;
MultiplayerDebugComponentReporter* m_currentComponentReport = nullptr;
AZStd::map<AZStd::string, MultiplayerDebugComponentReporter> m_componentReports;
MultiplayerDebugByteReporter m_gdeDirtyBytes;
AZStd::string m_entityName;
};
@@ -1,29 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Component/EntityId.h>
#include <Multiplayer/MultiplayerTypes.h>
namespace MultiplayerDiagnostics
{
class MultiplayerIPerEntityStats
{
public:
AZ_RTTI(MultiplayerIPerEntityStats, "{91A1E4F0-8AE6-44B2-89DF-DA34134C408A}");
virtual void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) = 0;
virtual void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) = 0;
virtual void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) = 0;
virtual void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0;
virtual void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0;
virtual void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) = 0;
virtual void RecordRpcReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) = 0;
};
}
@@ -34,7 +34,7 @@ AZ_CVAR(AZ::Color, net_DebugNetworkEntity_WarningColor, AZ::Colors::Red, nullptr
AZ_CVAR(AZ::Color, net_DebugNetworkEntity_BelowWarningColor, AZ::Colors::Grey, nullptr, AZ::ConsoleFunctorFlags::Null,
"If true, prints debug text over entities that use a considerable amount of network traffic");
namespace MultiplayerDiagnostics
namespace Multiplayer
{
#if defined(IMGUI_ENABLED)
static const ImVec4 k_ImGuiTomato = ImVec4(1.0f, 0.4f, 0.3f, 1.0f);
@@ -64,12 +64,12 @@ namespace MultiplayerDiagnostics
}
// --------------------------------------------------------------------------------------------
void DisplayReplicatedStateReport(AZStd::map<AZStd::string, ComponentReporter>& componentReports, float kbpsWarn, float maxWarn)
void DisplayReplicatedStateReport(AZStd::map<AZStd::string, MultiplayerDebugComponentReporter>& componentReports, float kbpsWarn, float maxWarn)
{
for (auto& componentPair : componentReports)
{
ImGui::Separator();
ComponentReporter& componentReport = componentPair.second;
MultiplayerDebugComponentReporter& componentReport = componentPair.second;
if (ReplicatedStateTreeNode(componentPair.first, componentReport, k_ImGuiCyan, 1))
{
@@ -94,7 +94,7 @@ namespace MultiplayerDiagnostics
const float kbitsLastSecond = fieldReport.GetKbitsPerSecond();
const ImVec4* textColor = &k_ImGuiWhite;
if (fieldReport.GetMaxBytes() > maxWarn)
if (aznumeric_cast<float>(fieldReport.GetMaxBytes()) > maxWarn)
{
textColor = &k_ImGuiKhaki;
}
@@ -133,6 +133,37 @@ namespace MultiplayerDiagnostics
: m_updateDebugOverlay([this]() { UpdateDebugOverlay(); }, AZ::Name("UpdateDebugPerEntityOverlay"))
{
m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true);
m_eventHandlers.m_entitySerializeStart = decltype(m_eventHandlers.m_entitySerializeStart)([this](AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName)
{
RecordEntitySerializeStart(mode, entityId, entityName);
});
m_eventHandlers.m_componentSerializeEnd = decltype(m_eventHandlers.m_componentSerializeEnd)([this](AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId)
{
RecordComponentSerializeEnd(mode, netComponentId);
});
m_eventHandlers.m_entitySerializeStop = decltype(m_eventHandlers.m_entitySerializeStop)([this](AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName)
{
RecordEntitySerializeStop(mode, entityId, entityName);
});
m_eventHandlers.m_propertySent = decltype(m_eventHandlers.m_propertySent)([this](Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes)
{
RecordPropertySent(netComponentId, propertyId, totalBytes);
});
m_eventHandlers.m_propertyReceived = decltype(m_eventHandlers.m_propertyReceived)([this](Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes)
{
RecordPropertyReceived(netComponentId, propertyId, totalBytes);
});
m_eventHandlers.m_rpcSent = decltype(m_eventHandlers.m_rpcSent)([this](AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes)
{
RecordRpcSent(entityId, entityName, netComponentId, rpcId, totalBytes);
});
m_eventHandlers.m_rpcReceived = decltype(m_eventHandlers.m_rpcReceived)([this](AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes)
{
RecordRpcSent(entityId, entityName, netComponentId, rpcId, totalBytes);
});
GetMultiplayer()->GetStats().ConnectHandlers(m_eventHandlers);
}
MultiplayerDebugPerEntityReporter::~MultiplayerDebugPerEntityReporter()
@@ -149,7 +180,7 @@ namespace MultiplayerDiagnostics
if (ImGui::CollapsingHeader("Receiving Entities"))
{
for (AZStd::pair<AZ::EntityId, EntityReporter>& entityPair : m_receivingEntityReports)
for (AZStd::pair<AZ::EntityId, MultiplayerDebugEntityReporter>& entityPair : m_receivingEntityReports)
{
if (!filter.PassFilter(entityPair.second.GetEntityName()))
{
@@ -167,7 +198,7 @@ namespace MultiplayerDiagnostics
if (ImGui::CollapsingHeader("Sending Entities"))
{
for (AZStd::pair<AZ::EntityId, EntityReporter>& entityPair : m_sendingEntityReports)
for (AZStd::pair<AZ::EntityId, MultiplayerDebugEntityReporter>& entityPair : m_sendingEntityReports)
{
const char* name = entityPair.second.GetEntityName();
if (!filter.PassFilter(name))
@@ -255,26 +286,38 @@ namespace MultiplayerDiagnostics
}
}
void MultiplayerDebugPerEntityReporter::RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes)
void MultiplayerDebugPerEntityReporter::RecordRpcSent(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes)
{
if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry())
{
// MultiplayerDebugByteReporter requires a
RecordEntitySerializeStart(AzNetworking::SerializerMode::ReadFromObject, entityId, entityName);
m_currentSendingEntityReport.ReportField(static_cast<AZ::u32>(netComponentId),
componentRegistry->GetComponentName(netComponentId),
componentRegistry->GetComponentRpcName(netComponentId, rpcId), totalBytes);
RecordComponentSerializeEnd(AzNetworking::SerializerMode::ReadFromObject, netComponentId);
RecordEntitySerializeStop(AzNetworking::SerializerMode::ReadFromObject, entityId, entityName);
}
}
void MultiplayerDebugPerEntityReporter::RecordRpcReceived(
AZ::EntityId entityId, const char* entityName,
Multiplayer::NetComponentId netComponentId,
Multiplayer::RpcIndex rpcId,
uint32_t totalBytes)
{
if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry())
{
RecordEntitySerializeStart(AzNetworking::SerializerMode::WriteToObject, entityId, entityName);
m_currentReceivingEntityReport.ReportField(static_cast<AZ::u32>(netComponentId),
componentRegistry->GetComponentName(netComponentId),
componentRegistry->GetComponentRpcName(netComponentId, rpcId), totalBytes);
RecordComponentSerializeEnd(AzNetworking::SerializerMode::WriteToObject, netComponentId);
RecordEntitySerializeStop(AzNetworking::SerializerMode::WriteToObject, entityId, entityName);
}
}
@@ -284,13 +327,13 @@ namespace MultiplayerDiagnostics
{
m_networkEntitiesTraffic.clear();
for (AZStd::pair<AZ::EntityId, EntityReporter>& entityPair : m_receivingEntityReports)
for (AZStd::pair<AZ::EntityId, MultiplayerDebugEntityReporter>& entityPair : m_receivingEntityReports)
{
m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName();
m_networkEntitiesTraffic[entityPair.first].m_down = entityPair.second.GetKbitsPerSecond();
}
for (AZStd::pair<AZ::EntityId, EntityReporter>& entityPair : m_sendingEntityReports)
for (AZStd::pair<AZ::EntityId, MultiplayerDebugEntityReporter>& entityPair : m_sendingEntityReports)
{
m_networkEntitiesTraffic[entityPair.first].m_name = entityPair.second.GetEntityName();
m_networkEntitiesTraffic[entityPair.first].m_up = entityPair.second.GetKbitsPerSecond();
@@ -10,38 +10,35 @@
#include "MultiplayerDebugByteReporter.h"
#include <AzCore/Component/EntityId.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/EBus/ScheduledEvent.h>
#include <AzCore/Interface/Interface.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <Debug/MultiplayerDebugPerEntityInterface.h>
#include <GridMate/Drillers/CarrierDriller.h>
#include <Multiplayer/MultiplayerStats.h>
#include <Multiplayer/MultiplayerTypes.h>
namespace MultiplayerDiagnostics
namespace Multiplayer
{
/**
* \brief GridMate network live analysis tool via ImGui.
*/
class MultiplayerDebugPerEntityReporter
: public AZ::Interface<MultiplayerIPerEntityStats>::Registrar
{
public:
MultiplayerDebugPerEntityReporter();
~MultiplayerDebugPerEntityReporter() override;
~MultiplayerDebugPerEntityReporter();
// main update loop
void OnImGuiUpdate();
//! MultilayerIPerEntityStats
//! Event handlers
// @{
void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) override;
void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) override;
void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) override;
void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override;
void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override;
void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) override;
void RecordRpcReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) override;
void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName);
void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId);
void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName);
void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes);
void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes);
void RecordRpcSent(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes);
void RecordRpcReceived(AZ::EntityId entityId, const char* entityName, Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes);
// }@
void UpdateDebugOverlay();
@@ -49,12 +46,13 @@ namespace MultiplayerDiagnostics
private:
AZ::ScheduledEvent m_updateDebugOverlay;
Multiplayer::MultiplayerStats::EventHandlers m_eventHandlers;
AZStd::map<AZ::EntityId, EntityReporter> m_sendingEntityReports{};
EntityReporter m_currentSendingEntityReport;
AZStd::map<AZ::EntityId, MultiplayerDebugEntityReporter> m_sendingEntityReports{};
MultiplayerDebugEntityReporter m_currentSendingEntityReport;
AZStd::map<AZ::EntityId, EntityReporter> m_receivingEntityReports{};
EntityReporter m_currentReceivingEntityReport;
AZStd::map<AZ::EntityId, MultiplayerDebugEntityReporter> m_receivingEntityReports{};
MultiplayerDebugEntityReporter m_currentReceivingEntityReport;
float m_replicatedStateKbpsWarn = 10.f;
float m_replicatedStateMaxSizeWarn = 30.f;
@@ -55,7 +55,7 @@ namespace Multiplayer
void MultiplayerDebugSystemComponent::OnImGuiInitialize()
{
m_reporter = AZStd::make_unique<MultiplayerDiagnostics::MultiplayerDebugPerEntityReporter>();
m_reporter = AZStd::make_unique<MultiplayerDebugPerEntityReporter>();
}
#ifdef IMGUI_ENABLED
@@ -65,7 +65,7 @@ namespace Multiplayer
{
ImGui::Checkbox("Networking Stats", &m_displayNetworkingStats);
ImGui::Checkbox("Multiplayer Stats", &m_displayMultiplayerStats);
ImGui::Checkbox("Multiplayer Per Entity Stats", &m_displayPerEntityStats);
ImGui::Checkbox("Multiplayer Entity Stats", &m_displayPerEntityStats);
ImGui::EndMenu();
}
}
@@ -53,6 +53,6 @@ namespace Multiplayer
bool m_displayMultiplayerStats = false;
bool m_displayPerEntityStats = false;
AZStd::unique_ptr<MultiplayerDiagnostics::MultiplayerDebugPerEntityReporter> m_reporter;
AZStd::unique_ptr<MultiplayerDebugPerEntityReporter> m_reporter;
};
}