You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/Multiplayer/Code/Source/MultiplayerStats.cpp

189 lines
8.8 KiB
C++

/*
* 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 <Multiplayer/MultiplayerStats.h>
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<uint16_t>(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<uint16_t>(netComponentId);
const uint16_t propertyIndex = aznumeric_cast<uint16_t>(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<uint16_t>(netComponentId);
const uint16_t propertyIndex = aznumeric_cast<uint16_t>(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<uint16_t>(netComponentId);
const uint16_t rpcIndex = aznumeric_cast<uint16_t>(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<uint16_t>(netComponentId);
const uint16_t rpcIndex = aznumeric_cast<uint16_t>(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<AZ::TimeMs>(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<MultiplayerStats::Metric>& 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<uint16_t>(netComponentId);
return SumMetricVector(m_componentStats[netComponentIndex].m_propertyUpdatesSent);
}
MultiplayerStats::Metric MultiplayerStats::CalculateComponentPropertyUpdateRecvMetrics(NetComponentId netComponentId) const
{
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
return SumMetricVector(m_componentStats[netComponentIndex].m_propertyUpdatesRecv);
}
MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsSentMetrics(NetComponentId netComponentId) const
{
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
return SumMetricVector(m_componentStats[netComponentIndex].m_rpcsSent);
}
MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsRecvMetrics(NetComponentId netComponentId) const
{
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(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<NetComponentId>(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<NetComponentId>(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<NetComponentId>(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<NetComponentId>(index);
CombineMetrics(result, CalculateComponentRpcsRecvMetrics(netComponentId));
}
return result;
}
}