using System;
using System.Collections;
using System.Diagnostics;
using System.Threading.Tasks;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace LibMMD.Unity3D
{
/// Measures load stages without mixing timing and log formatting into the loader.
internal sealed class MmdLoadDiagnostics
{
private readonly Func _isEnabled;
private readonly string _modelPath;
private readonly Stopwatch _total = Stopwatch.StartNew();
internal MmdLoadDiagnostics(Func isEnabled, string modelPath)
{
_isEnabled = isEnabled ?? throw new ArgumentNullException(nameof(isEnabled));
_modelPath = modelPath;
}
internal IEnumerator Measure(string stage, IEnumerator routine)
{
if (!_isEnabled())
{
while (routine.MoveNext()) yield return routine.Current;
yield break;
}
var wall = Stopwatch.StartNew();
var activeTicks = 0L;
var maximumSliceTicks = 0L;
var steps = 0;
while (true)
{
var started = Stopwatch.GetTimestamp();
var moved = routine.MoveNext();
var elapsed = Stopwatch.GetTimestamp() - started;
activeTicks += elapsed;
if (elapsed > maximumSliceTicks) maximumSliceTicks = elapsed;
steps++;
if (!moved) break;
yield return routine.Current;
}
wall.Stop();
var tickToMilliseconds = 1000d / Stopwatch.Frequency;
Debug.LogFormat(
"[LibMMD.Load] {0}: wall={1:F1} ms, main={2:F1} ms, maxSlice={3:F1} ms, steps={4}",
stage, wall.Elapsed.TotalMilliseconds, activeTicks * tickToMilliseconds,
maximumSliceTicks * tickToMilliseconds, steps);
}
internal void MeasureAtomic(string stage, Action action)
{
if (!_isEnabled())
{
action();
return;
}
var timer = Stopwatch.StartNew();
action();
timer.Stop();
Debug.LogFormat("[LibMMD.Load] {0}: main={1:F1} ms, maxSlice={1:F1} ms",
stage, timer.Elapsed.TotalMilliseconds);
}
internal void Complete()
{
_total.Stop();
if (_isEnabled())
Debug.LogFormat("[LibMMD.Load] total: wall={0:F1} ms ({1})",
_total.Elapsed.TotalMilliseconds, _modelPath);
}
internal static IEnumerator WaitForTask(Task task)
{
while (!task.IsCompleted) yield return null;
}
}
}