Files
dungeons/Assets/Plugins/Zenject/Source/Util/ProfileTimers.cs

169 lines
4.4 KiB
C#

#if ZEN_INTERNAL_PROFILING
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ModestTree;
namespace Zenject
{
// Similar to ProfileBlock except used for measuring speed of zenject specifically
// And does not use unity's profiler
public static class ProfileTimers
{
static Dictionary<string, TimerInfo> _timers = new Dictionary<string, TimerInfo>();
public static void ResetAll()
{
foreach (var timer in _timers.Values)
{
timer.Reset();
}
}
public static string FormatResults()
{
var result = new StringBuilder();
// Uncomment if you only want to see zenject related info
//var timers = _timers.Where(x => x.Key != "User Code");
var timers = _timers;
var total = timers.Select(x => x.Value.TotalMilliseconds).Sum();
result.Append("Total time tracked: {0:0.00} ms. Details:".Fmt(total));
foreach (var pair in timers.OrderByDescending(x => x.Value.TotalMilliseconds))
{
var time = pair.Value.TotalMilliseconds;
var percent = 100.0 * (time / total);
var name = pair.Key;
result.Append("\n {0:00.0}% ({1:00000}x) ({2:0000} ms) {3}".Fmt(percent, pair.Value.CallCount, time, name));
}
return result.ToString();
}
public static double GetTimerElapsedMilliseconds(string name)
{
return _timers[name].TotalMilliseconds;
}
public static IDisposable CreateTimedBlock(string name)
{
TimerInfo timer;
if (!_timers.TryGetValue(name, out timer))
{
timer = new TimerInfo();
_timers.Add(name, timer);
}
timer.CallCount++;
if (timer.IsRunning)
{
return null;
}
return TimedBlock.Pool.Spawn(timer);
}
class TimedBlock : IDisposable
{
public static StaticMemoryPool<TimerInfo, TimedBlock> Pool =
new StaticMemoryPool<TimerInfo, TimedBlock>(OnSpawned, OnDespawned);
readonly List<TimerInfo> _pausedTimers = new List<TimerInfo>();
TimerInfo _exclusiveTimer;
static void OnSpawned(
TimerInfo exclusiveTimer, TimedBlock instance)
{
Assert.That(instance._pausedTimers.Count == 0);
instance._exclusiveTimer = exclusiveTimer;
foreach (var timer in _timers.Values)
{
if (exclusiveTimer == timer)
{
Assert.That(!timer.IsRunning);
timer.Resume();
}
else if (timer.IsRunning)
{
timer.Pause();
instance._pausedTimers.Add(timer);
}
}
}
static void OnDespawned(TimedBlock instance)
{
Assert.That(instance._exclusiveTimer.IsRunning);
instance._exclusiveTimer.Pause();
foreach (var timer in instance._pausedTimers)
{
Assert.That(!timer.IsRunning);
timer.Resume();
}
instance._pausedTimers.Clear();
}
public void Dispose()
{
Pool.Despawn(this);
}
}
public class TimerInfo
{
readonly Stopwatch _timer;
public TimerInfo()
{
_timer = new Stopwatch();
}
public int CallCount
{
get; set;
}
public double TotalMilliseconds
{
get { return _timer.Elapsed.TotalMilliseconds; }
}
public bool IsRunning
{
get { return _timer.IsRunning; }
}
public void Reset()
{
_timer.Reset();
}
public void Resume()
{
_timer.Start();
}
public void Pause()
{
_timer.Stop();
}
}
}
}
#endif