using System;
using System.Collections.Generic;
using Unity.PerformanceTesting.Runtime;
using Unity.Profiling;
using UnityEngine;
namespace Unity.PerformanceTesting.Measurements
{
class ProfilerMarkerMeasurement : IDisposable
{
private readonly bool m_AverageSampleMeasurement;
bool m_DisposedValue;
protected struct RecordedSampleGroup
{
public SampleGroup SampleGroup;
public ProfilerRecorder ProfilerRecorder;
}
protected readonly List<RecordedSampleGroup> m_SampleGroups = new List<RecordedSampleGroup>();
public ProfilerMarkerMeasurement(bool averageSampleMeasurement)
{
m_AverageSampleMeasurement = averageSampleMeasurement;
}
public void AddAndEnableProfilerSampleGroup(IEnumerable<SampleGroup> sampleGroups)
{
foreach (var sampleGroup in sampleGroups)
{
AddAndEnableProfilerSample(sampleGroup);
}
}
public void AddAndEnableProfilerSample(SampleGroup sampleGroup)
{
var recorder = new ProfilerRecorder(sampleGroup.Name, 1, ProfilerRecorderOptions.WrapAroundWhenCapacityReached | ProfilerRecorderOptions.SumAllSamplesInFrame);
// Start recorder immediately
recorder.Start();
m_SampleGroups.Add(new RecordedSampleGroup { SampleGroup = sampleGroup, ProfilerRecorder = recorder });
}
public void SampleProfilerSamples(bool stopRecorders = false)
{
foreach (var sampleGroup in m_SampleGroups)
{
// Validate that the recorder is attached to a valid marker
if (!sampleGroup.ProfilerRecorder.Valid)
{
Debug.LogError($"ProfilerMarker measurement is attached to invalid marker \"{sampleGroup.SampleGroup.Name}\"! Ensure the marker is created at the time of the measurement");
continue;
}
if (stopRecorders)
sampleGroup.ProfilerRecorder.Stop();
var delta = 0.0;
// Record the last recorded value if present, otherwise use 0.
if (sampleGroup.ProfilerRecorder.Count > 0 && sampleGroup.ProfilerRecorder.GetSample(0).Count > 0)
{
var sampleCount = m_AverageSampleMeasurement ? sampleGroup.ProfilerRecorder.GetSample(0).Count : 1;
if (sampleCount > 0)
{
var totalTimeNs = sampleGroup.ProfilerRecorder.GetSample(0).Value / sampleCount;
delta = Utils.ConvertSample(SampleUnit.Nanosecond, sampleGroup.SampleGroup.Unit, totalTimeNs);
}
}
Measure.Custom(sampleGroup.SampleGroup, delta);
}
}
public void StopAndSampleRecorders() => SampleProfilerSamples(true);
protected virtual void Dispose(bool disposing)
{
if (m_DisposedValue)
return;
foreach (var sampleGroup in m_SampleGroups)
{
sampleGroup.ProfilerRecorder.Dispose();
}
m_DisposedValue = true;
}
~ProfilerMarkerMeasurement()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: false);
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}