Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [1.0.0-pre.8] - 2022-06-15

### *Runtime Net Stats Monitor*
- Clamping numerical values to acceptable limits for public APIs
- Improve generated counter labels
- Prevent an exception when there's only one sample
- Added spacing between divider graph and axis number alignment
- Reusing existing numerical labels when the value doesn't change or barely changed
- Fix incorrect values for gauges in counter display elements using SMA
- Ensure RNSM counters display 1 rather than 1,000 milli
- Use infinity rather than float.Min for counter config bounds
- Reduce vertices in graphs with large sample count
  • Loading branch information
Unity Technologies committed Jun 15, 2022
1 parent 27bd672 commit d8f6369
Show file tree
Hide file tree
Showing 77 changed files with 3,175 additions and 456 deletions.
4 changes: 4 additions & 0 deletions .buginfo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
system: jira
server: jira.unity3d.com
project: MTL
issuetype: Bug
24 changes: 24 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## Purpose of this PR
_Describe the purpose of the PR_
- [ ] **CHANGELOG** updated with all public facing changes (API changes, UI/UX changes, behaviour changes)
- [ ] No need to update the **CHANGELOG**

## Jira ticket
_Full link to related jira ticket_

## Functional Testing
_Have you performed:_
- [ ] `Manual testing`

## Performance Testing
_**Remove this section if not applicable** - describe the performance testing done_

## Overall Changes Risks
_Does the change require QA team to_
- [ ] `Review automated tests`
- [ ] `Execute manual tests`

If any boxes above are checked, please add QA as a PR reviewer.

## UI and Visual Changes
_**Remove this section if not applicable** - Add images of the visual before and after your changes_
25 changes: 19 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [1.0.0-pre.8] - 2022-06-15

### *Runtime Net Stats Monitor*
- Clamping numerical values to acceptable limits for public APIs
- Improve generated counter labels
- Prevent an exception when there's only one sample
- Added spacing between divider graph and axis number alignment
- Reusing existing numerical labels when the value doesn't change or barely changed
- Fix incorrect values for gauges in counter display elements using SMA
- Ensure RNSM counters display 1 rather than 1,000 milli
- Use infinity rather than float.Min for counter config bounds
- Reduce vertices in graphs with large sample count

## [1.0.0-pre.7] - 2022-04-27

### *Runtime Net Stats Monitor*
Expand All @@ -15,16 +28,16 @@ For more information about the Runtime Net Stats Monitor, please see its documen
## [1.0.0-pre.6] - 2022-02-28

### *Network Profiler*
- Changed NetworkMessage to use the name of the message in the Type column (#133)
- Changed NetworkMessage to use the name of the message in the Type column

### *Metrics*
- Added throttling to event metric types (#142)
- Added a system to generate random data for tests (#141)
- Refactored underlying data structures to reduce redundancy (#146)
- Added throttling to event metric types
- Added a system to generate random data for tests
- Refactored underlying data structures to reduce redundancy
- Dramatically reduced runtime allocations caused by dispatching metrics to the profiler by updating the serialization implementation to use native buffers instead of BinaryFormatter
- Deprecated support for String when collecting metric payloads
- Added RTT to server metrics (#192)
- Added Packet count to metrics (#180)
- Added RTT to server metrics
- Added Packet count to metrics

### *Misc*
- Updated some internals exposed flags to enable some test improvements on NGO side
Expand Down
8 changes: 5 additions & 3 deletions Common/Runtime/Data/ContinuousExponentialMovingAverage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ namespace Unity.Multiplayer.Tools.Common
/// </remarks>
internal class ContinuousExponentialMovingAverage
{
const double k_DefaultInitialTime = double.NegativeInfinity;

public static readonly double k_ln2 = Math.Log(2);

/// The decay constant is λ = ln(2) / HalfLife. A larger decay constant will results in a faster,
Expand All @@ -40,7 +42,7 @@ public static ContinuousExponentialMovingAverage CreateWithHalfLife(double halfL
/// less responsive CEMA with more smoothing.
public static double GetDecayConstantForHalfLife(double halfLife) => k_ln2 / halfLife;

public ContinuousExponentialMovingAverage(double decayConstant, double value = 0d, double time = Double.MinValue)
public ContinuousExponentialMovingAverage(double decayConstant, double value = 0d, double time = k_DefaultInitialTime)
{
if (decayConstant < 0)
{
Expand All @@ -57,13 +59,13 @@ public void Reset()
{
DecayConstant = 0;
LastValue = 0;
LastTime = Double.MinValue;
LastTime = k_DefaultInitialTime;
}

public void ClearValueAndTime()
{
LastValue = 0;
LastTime = Double.MinValue;
LastTime = k_DefaultInitialTime;
}

/// Adds a new sample to the Continuous Exponential Moving Average (CEMA).
Expand Down
13 changes: 5 additions & 8 deletions Common/Runtime/Data/RingBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ namespace Unity.Multiplayer.Tools.Common
/// A ring buffer, indexed from least recent (beginning at 0) to most recent (ending at length - 1).
/// It is possible for a RingBuffer to have zero capacity, in which case it does not allocate storage,
/// ignores values that are pushed to it, and its length will always be zero.
internal class RingBuffer<T>
: IEnumerable<T>
class RingBuffer<T> : IEnumerable<T>
{
/// Backing buffer, null in the event that the buffer has zero capacity
[CanBeNull]
Expand All @@ -19,7 +18,7 @@ internal class RingBuffer<T>
int m_Begin;

/// The number of values stored
public int Length { get; private set; }
public int Length { get; set; }

/// The capacity of the ring buffer.
/// Writing to the capacity will resize the ring buffer if necessary,
Expand Down Expand Up @@ -238,16 +237,14 @@ public T GetValueOrDefault(Index index)

/// <exception cref="IndexOutOfRangeException">Throws IndexOutOfRange if length is 0</exception>
public T LeastRecent => this[0];
public T LeastRecentOrDefault => Length > 0 ? LeastRecent : default;

#if UNITY_2021_2_OR_NEWER // Index and ^i syntax are not available in lower versions
/// <exception cref="IndexOutOfRangeException">Throws IndexOutOfRange if length is 0</exception>
public T MostRecent => this[^0];
public T MostRecent => this[^1];
public T MostRecentOrDefault => Length > 0 ? MostRecent : default;
#endif

public T LeastRecentOrDefault => Length > 0 ? m_Buffer![m_Begin] : default;

public T MostRecentOrDefault => Length > 0 ? m_Buffer![m_Begin + Length - 1] : default;

/// Enumerator from least to most recent
public IEnumerator<T> GetEnumerator()
{
Expand Down
45 changes: 42 additions & 3 deletions Common/Runtime/Data/RingBufferExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,48 @@
using System;

namespace Unity.Multiplayer.Tools.Common
{
internal static class RingBufferExtensions
static class RingBufferExtensions
{
// Unfortunately in C# it's not possible to implement these Sum and Average extensions
// generically without imposing additional overhead, as it would be with C++ templates
// Unfortunately in C# it's not possible to implement these methods generically
// without imposing additional overhead, as it would be with C++ templates.
// The reason we're using extension methods on RingBuffer here, rather than normal methods,
// is that normal methods on generic types do not allow us to implement them for only some type
// arguments, whereas with extension methods we can implement RingBuffer<int>.Max() without
// implementing RingBuffer<T>.Max() for all T.

public static int Max(this RingBuffer<int> ring)
{
int max = 0;
var count = ring.Length;
for (var i = 0; i < count; ++i)
{
max = Math.Max(max, ring[i]);
}
return max;
}

public static long Max(this RingBuffer<long> ring)
{
long max = 0;
var count = ring.Length;
for (var i = 0; i < count; ++i)
{
max = Math.Max(max, ring[i]);
}
return max;
}

public static float Max(this RingBuffer<float> ring)
{
float max = 0;
var count = ring.Length;
for (var i = 0; i < count; ++i)
{
max = Math.Max(max, ring[i]);
}
return max;
}

public static int Sum(this RingBuffer<int> ring)
{
Expand Down
18 changes: 9 additions & 9 deletions Common/Tests/Data/ContinuousExponentialMovingAverageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ internal class ContinuousExponentialMovingAverageTests
public void InitializedCorrectlyWithOneArgument(double decayConstant)
{
var ema = new ContinuousExponentialMovingAverage(decayConstant);
Assert.AreEqual(ema.DecayConstant, decayConstant);
Assert.AreEqual(ema.LastValue, 0f);
Assert.AreEqual(ema.LastTime, Double.MinValue);
Assert.AreEqual(decayConstant, ema.DecayConstant);
Assert.AreEqual(0f, ema.LastValue);
Assert.AreEqual(Double.NegativeInfinity, ema.LastTime);
}

[TestCase(0.5)]
Expand All @@ -25,8 +25,8 @@ public void InitializedCorrectlyWithTwoArguments(
double initialValue = 0f)
{
var ema = new ContinuousExponentialMovingAverage(decayConstant, initialValue);
Assert.AreEqual(ema.DecayConstant, decayConstant);
Assert.AreEqual(ema.LastValue, initialValue);
Assert.AreEqual(decayConstant, ema.DecayConstant);
Assert.AreEqual(initialValue, ema.LastValue);
}

[TestCase(0.5)]
Expand All @@ -41,8 +41,8 @@ public void InitializedCorrectlyWithThreeArguments(
double initialTime = Double.MinValue)
{
var ema = new ContinuousExponentialMovingAverage(decayConstant, initialValue, initialTime);
Assert.AreEqual(ema.DecayConstant, decayConstant);
Assert.AreEqual(ema.LastValue, initialValue);
Assert.AreEqual(decayConstant, ema.DecayConstant);
Assert.AreEqual(initialValue, ema.LastValue);
}

[TestCase(1)]
Expand Down Expand Up @@ -80,7 +80,7 @@ public void CreateWithHalfLifeIsWorkingCorrectly(double halfLife)
var cema = ContinuousExponentialMovingAverage.CreateWithHalfLife(halfLife);
Assert.AreEqual(ContinuousExponentialMovingAverage.k_ln2 / halfLife, cema.DecayConstant);
Assert.AreEqual(0d, cema.LastValue);
Assert.AreEqual(Double.MinValue, cema.LastTime);
Assert.AreEqual(Double.NegativeInfinity, cema.LastTime);
}

[TestCase(-89.30, 4.7)]
Expand All @@ -92,7 +92,7 @@ public void ConstructedWithDefaultTimeAssumesNextInstantaneousSample(double time
{
var cema = ContinuousExponentialMovingAverage.CreateWithHalfLife(0.5);
Assert.AreEqual(0, cema.LastValue);
Assert.AreEqual(Double.MinValue, cema.LastTime);
Assert.AreEqual(Double.NegativeInfinity, cema.LastTime);

cema.AddSampleForGauge(value, time);
Assert.AreEqual(value, cema.LastValue);
Expand Down
38 changes: 38 additions & 0 deletions Common/Tests/Data/RingBufferTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,44 @@ public void RingBufferPreservesValuesWhenCapacityIsDecreased()
Assert.AreEqual(ring.Length, 4);
Assert.AreEqual(new List<byte> { 8, 13, 21, 34 }, ring.ToList());
}

[Test]
public void RingBufferMostAndLeastRecentAreCorrect()
{
var ring = new RingBuffer<byte>(4);

ring.PushBack(7); // => 7
Assert.AreEqual(7, ring.MostRecent);
Assert.AreEqual(7, ring.LeastRecent);

ring.PushBack(3); // => 3 7
Assert.AreEqual(3, ring.MostRecent);
Assert.AreEqual(7, ring.LeastRecent);

ring.PushBack(5); // => 5 3 7
Assert.AreEqual(5, ring.MostRecent);
Assert.AreEqual(7, ring.LeastRecent);

ring.PushBack(11); // => 11 5 3 7
Assert.AreEqual(11, ring.MostRecent);
Assert.AreEqual(7, ring.LeastRecent);

ring.PushBack(14); // => 14 11 5 3
Assert.AreEqual(14, ring.MostRecent);
Assert.AreEqual(3, ring.LeastRecent);

ring.PushBack(6); // => 6 14 11 5
Assert.AreEqual(6, ring.MostRecent);
Assert.AreEqual(5, ring.LeastRecent);

ring.PushBack(12); // => 12 6 14 11
Assert.AreEqual(12, ring.MostRecent);
Assert.AreEqual(11, ring.LeastRecent);

ring.PushBack(4); // => 4 12 6 14
Assert.AreEqual(4, ring.MostRecent);
Assert.AreEqual(14, ring.LeastRecent);
}
}
}
#endif
16 changes: 16 additions & 0 deletions MetricTypes/Runtime/MetricTypes/MetricType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ public enum DirectedMetricType
/// <summary>
/// Number of RPC sent.
/// </summary>
[MetricMetadata(DisplayName = "RPCs Sent")]
RpcSent = (MT.Rpc << NDC.k_BitWidth) | ND.Sent,
/// <summary>
/// Number of RPC received.
/// </summary>
[MetricMetadata(DisplayName = "RPCs Received")]
RpcReceived = (MT.Rpc << NDC.k_BitWidth) | ND.Received,

/// <summary>
Expand Down Expand Up @@ -83,64 +85,78 @@ public enum DirectedMetricType
/// <summary>
/// Number of network variable delta message sent.
/// </summary>
[MetricMetadata(DisplayName = "Network Variable Deltas Sent")]
NetworkVariableDeltaSent = (MT.NetworkVariableDelta << NDC.k_BitWidth) | ND.Sent,
/// <summary>
/// Number of network variable delta message received.
/// </summary>
[MetricMetadata(DisplayName = "Network Variable Deltas Received")]
NetworkVariableDeltaReceived = (MT.NetworkVariableDelta << NDC.k_BitWidth) | ND.Received,

/// <summary>
/// Number of network object spawned message sent.
/// </summary>
[MetricMetadata(DisplayName = "Objects Spawned Sent")]
ObjectSpawnedSent = (MT.ObjectSpawned << NDC.k_BitWidth) | ND.Sent,
/// <summary>
/// Number of network object spawned message received.
/// </summary>
[MetricMetadata(DisplayName = "Objects Spawned Received")]
ObjectSpawnedReceived = (MT.ObjectSpawned << NDC.k_BitWidth) | ND.Received,

/// <summary>
/// Number of network object destroyed message sent.
/// </summary>
[MetricMetadata(DisplayName = "Objects Destroyed Sent")]
ObjectDestroyedSent = (MT.ObjectDestroyed << NDC.k_BitWidth) | ND.Sent,
/// <summary>
/// Number of network object destroyed message received.
/// </summary>
[MetricMetadata(DisplayName = "Objects Destroyed Received")]
ObjectDestroyedReceived = (MT.ObjectDestroyed << NDC.k_BitWidth) | ND.Received,

/// <summary>
/// Number of ownership change message sent.
/// </summary>
[MetricMetadata(DisplayName = "Ownership Changes Sent")]
OwnershipChangeSent = (MT.OwnershipChange << NDC.k_BitWidth) | ND.Sent,
/// <summary>
/// Number of ownership change message received.
/// </summary>
[MetricMetadata(DisplayName = "Ownership Changes Received")]
OwnershipChangeReceived = (MT.OwnershipChange << NDC.k_BitWidth) | ND.Received,

/// <summary>
/// Number of server log message sent.
/// </summary>
[MetricMetadata(DisplayName = "Server Logs Sent")]
ServerLogSent = (MT.ServerLog << NDC.k_BitWidth) | ND.Sent,
/// <summary>
/// Number of server log message received.
/// </summary>
[MetricMetadata(DisplayName = "Server Logs Received")]
ServerLogReceived = (MT.ServerLog << NDC.k_BitWidth) | ND.Received,

/// <summary>
/// Number of scene event message sent.
/// </summary>
[MetricMetadata(DisplayName = "Scene Events Sent")]
SceneEventSent = (MT.SceneEvent << NDC.k_BitWidth) | ND.Sent,
/// <summary>
/// Number of scene event message received.
/// </summary>
[MetricMetadata(DisplayName = "Scene Events Received")]
SceneEventReceived = (MT.SceneEvent << NDC.k_BitWidth) | ND.Received,

/// <summary>
/// Number of network message sent.
/// </summary>
[MetricMetadata(DisplayName = "Network Messages Sent")]
NetworkMessageSent = (MT.NetworkMessage << NDC.k_BitWidth) | ND.Sent,
/// <summary>
/// Number of network message received.
/// </summary>
[MetricMetadata(DisplayName = "Network Messages Received")]
NetworkMessageReceived = (MT.NetworkMessage << NDC.k_BitWidth) | ND.Received,

/// <summary>
Expand Down
Loading

0 comments on commit d8f6369

Please sign in to comment.