/* * 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 * */ #include namespace Multiplayer { MultiplayerStats::Metric::Metric() { AZStd::uninitialized_fill_n(m_callHistory.data(), RingbufferSamples, 0); AZStd::uninitialized_fill_n(m_byteHistory.data(), RingbufferSamples, 0); } void MultiplayerStats::ReserveComponentStats(NetComponentId netComponentId, uint16_t propertyCount, uint16_t rpcCount) { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); if (m_componentStats.size() <= netComponentIndex) { m_componentStats.resize(netComponentIndex + 1); } m_componentStats[netComponentIndex].m_propertyUpdatesSent.resize(propertyCount); m_componentStats[netComponentIndex].m_propertyUpdatesRecv.resize(propertyCount); m_componentStats[netComponentIndex].m_rpcsSent.resize(rpcCount); m_componentStats[netComponentIndex].m_rpcsRecv.resize(rpcCount); } void MultiplayerStats::RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes) { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t propertyIndex = aznumeric_cast(propertyId); m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalCalls++; m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalBytes += totalBytes; m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_callHistory[m_recordMetricIndex]++; m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_byteHistory[m_recordMetricIndex] += totalBytes; } void MultiplayerStats::RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes) { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t propertyIndex = aznumeric_cast(propertyId); m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalCalls++; m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalBytes += totalBytes; m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_callHistory[m_recordMetricIndex]++; m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_byteHistory[m_recordMetricIndex] += totalBytes; } void MultiplayerStats::RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes) { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t rpcIndex = aznumeric_cast(rpcId); m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalCalls++; m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalBytes += totalBytes; m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_callHistory[m_recordMetricIndex]++; m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_byteHistory[m_recordMetricIndex] += totalBytes; } void MultiplayerStats::RecordRpcReceived(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes) { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); const uint16_t rpcIndex = aznumeric_cast(rpcId); m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalCalls++; m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalBytes += totalBytes; m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_callHistory[m_recordMetricIndex]++; m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_byteHistory[m_recordMetricIndex] += totalBytes; } void MultiplayerStats::TickStats(AZ::TimeMs metricFrameTimeMs) { m_totalHistoryTimeMs = metricFrameTimeMs * static_cast(RingbufferSamples); m_recordMetricIndex = ++m_recordMetricIndex % RingbufferSamples; for (ComponentStats& componentStats : m_componentStats) { for (Metric& metric : componentStats.m_propertyUpdatesSent) { metric.m_callHistory[m_recordMetricIndex] = 0; metric.m_byteHistory[m_recordMetricIndex] = 0; } for (Metric& metric : componentStats.m_propertyUpdatesRecv) { metric.m_callHistory[m_recordMetricIndex] = 0; metric.m_byteHistory[m_recordMetricIndex] = 0; } for (Metric& metric : componentStats.m_rpcsSent) { metric.m_callHistory[m_recordMetricIndex] = 0; metric.m_byteHistory[m_recordMetricIndex] = 0; } for (Metric& metric : componentStats.m_rpcsRecv) { metric.m_callHistory[m_recordMetricIndex] = 0; metric.m_byteHistory[m_recordMetricIndex] = 0; } } } static void CombineMetrics(MultiplayerStats::Metric& outArg1, const MultiplayerStats::Metric& arg2) { outArg1.m_totalCalls += arg2.m_totalCalls; outArg1.m_totalBytes += arg2.m_totalBytes; for (uint32_t index = 0; index < MultiplayerStats::RingbufferSamples; ++index) { outArg1.m_callHistory[index] += arg2.m_callHistory[index]; outArg1.m_byteHistory[index] += arg2.m_byteHistory[index]; } } static MultiplayerStats::Metric SumMetricVector(const AZStd::vector& metricVector) { MultiplayerStats::Metric result; for (AZStd::size_t index = 0; index < metricVector.size(); ++index) { CombineMetrics(result, metricVector[index]); } return result; } MultiplayerStats::Metric MultiplayerStats::CalculateComponentPropertyUpdateSentMetrics(NetComponentId netComponentId) const { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); return SumMetricVector(m_componentStats[netComponentIndex].m_propertyUpdatesSent); } MultiplayerStats::Metric MultiplayerStats::CalculateComponentPropertyUpdateRecvMetrics(NetComponentId netComponentId) const { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); return SumMetricVector(m_componentStats[netComponentIndex].m_propertyUpdatesRecv); } MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsSentMetrics(NetComponentId netComponentId) const { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); return SumMetricVector(m_componentStats[netComponentIndex].m_rpcsSent); } MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsRecvMetrics(NetComponentId netComponentId) const { const uint16_t netComponentIndex = aznumeric_cast(netComponentId); return SumMetricVector(m_componentStats[netComponentIndex].m_rpcsRecv); } MultiplayerStats::Metric MultiplayerStats::CalculateTotalPropertyUpdateSentMetrics() const { Metric result; for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index) { const NetComponentId netComponentId = aznumeric_cast(index); CombineMetrics(result, CalculateComponentPropertyUpdateSentMetrics(netComponentId)); } return result; } MultiplayerStats::Metric MultiplayerStats::CalculateTotalPropertyUpdateRecvMetrics() const { Metric result; for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index) { const NetComponentId netComponentId = aznumeric_cast(index); CombineMetrics(result, CalculateComponentPropertyUpdateRecvMetrics(netComponentId)); } return result; } MultiplayerStats::Metric MultiplayerStats::CalculateTotalRpcsSentMetrics() const { Metric result; for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index) { const NetComponentId netComponentId = aznumeric_cast(index); CombineMetrics(result, CalculateComponentRpcsSentMetrics(netComponentId)); } return result; } MultiplayerStats::Metric MultiplayerStats::CalculateTotalRpcsRecvMetrics() const { Metric result; for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index) { const NetComponentId netComponentId = aznumeric_cast(index); CombineMetrics(result, CalculateComponentRpcsRecvMetrics(netComponentId)); } return result; } }