211 lines
5.3 KiB
C#
211 lines
5.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text.RegularExpressions;
|
|
using ModestTree;
|
|
#if UNITY_EDITOR
|
|
using UnityEngine.Profiling;
|
|
using System.Threading;
|
|
#endif
|
|
|
|
namespace Zenject
|
|
{
|
|
[NoReflectionBaking]
|
|
public class ProfileBlock : IDisposable
|
|
{
|
|
#if UNITY_EDITOR
|
|
static int _blockCount;
|
|
static ProfileBlock _instance = new ProfileBlock();
|
|
static Dictionary<int, string> _nameCache = new Dictionary<int, string>();
|
|
|
|
ProfileBlock()
|
|
{
|
|
}
|
|
|
|
public static Thread UnityMainThread
|
|
{
|
|
get; set;
|
|
}
|
|
|
|
public static Regex ProfilePattern
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
static int GetHashCode(object p1, object p2)
|
|
{
|
|
unchecked // Overflow is fine, just wrap
|
|
{
|
|
int hash = 17;
|
|
hash = hash * 29 + p1.GetHashCode();
|
|
hash = hash * 29 + p2.GetHashCode();
|
|
return hash;
|
|
}
|
|
}
|
|
|
|
static int GetHashCode(object p1, object p2, object p3)
|
|
{
|
|
unchecked // Overflow is fine, just wrap
|
|
{
|
|
int hash = 17;
|
|
hash = hash * 29 + p1.GetHashCode();
|
|
hash = hash * 29 + p2.GetHashCode();
|
|
hash = hash * 29 + p3.GetHashCode();
|
|
return hash;
|
|
}
|
|
}
|
|
|
|
public static ProfileBlock Start(string sampleNameFormat, object obj1, object obj2)
|
|
{
|
|
#if ZEN_TESTS_OUTSIDE_UNITY
|
|
return null;
|
|
#else
|
|
if (UnityMainThread == null
|
|
|| !UnityMainThread.Equals(Thread.CurrentThread))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (!Profiler.enabled)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// We need to ensure that we do not have per-frame allocations in ProfileBlock
|
|
// to avoid infecting the test too much, so use a cache of formatted strings given
|
|
// the input values
|
|
// This only works if the input values do not change per frame
|
|
var hash = GetHashCode(sampleNameFormat, obj1, obj2);
|
|
|
|
string formatString;
|
|
|
|
if (!_nameCache.TryGetValue(hash, out formatString))
|
|
{
|
|
formatString = string.Format(sampleNameFormat, obj1, obj2);
|
|
_nameCache.Add(hash, formatString);
|
|
}
|
|
|
|
return StartInternal(formatString);
|
|
#endif
|
|
}
|
|
|
|
public static ProfileBlock Start(string sampleNameFormat, object obj)
|
|
{
|
|
#if ZEN_TESTS_OUTSIDE_UNITY
|
|
return null;
|
|
#else
|
|
if (UnityMainThread == null
|
|
|| !UnityMainThread.Equals(Thread.CurrentThread))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (!Profiler.enabled)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// We need to ensure that we do not have per-frame allocations in ProfileBlock
|
|
// to avoid infecting the test too much, so use a cache of formatted strings given
|
|
// the input values
|
|
// This only works if the input values do not change per frame
|
|
var hash = GetHashCode(sampleNameFormat, obj);
|
|
|
|
string formatString;
|
|
|
|
if (!_nameCache.TryGetValue(hash, out formatString))
|
|
{
|
|
formatString = string.Format(sampleNameFormat, obj);
|
|
_nameCache.Add(hash, formatString);
|
|
}
|
|
|
|
return StartInternal(formatString);
|
|
#endif
|
|
}
|
|
|
|
public static ProfileBlock Start(string sampleName)
|
|
{
|
|
#if ZEN_TESTS_OUTSIDE_UNITY
|
|
return null;
|
|
#else
|
|
if (UnityMainThread == null
|
|
|| !UnityMainThread.Equals(Thread.CurrentThread))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (!Profiler.enabled)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return StartInternal(sampleName);
|
|
#endif
|
|
}
|
|
|
|
static ProfileBlock StartInternal(string sampleName)
|
|
{
|
|
Assert.That(Profiler.enabled);
|
|
|
|
if (ProfilePattern == null || ProfilePattern.Match(sampleName).Success)
|
|
{
|
|
Profiler.BeginSample(sampleName);
|
|
_blockCount++;
|
|
return _instance;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_blockCount--;
|
|
Assert.That(_blockCount >= 0);
|
|
Profiler.EndSample();
|
|
}
|
|
|
|
#else
|
|
ProfileBlock(string sampleName, bool rootBlock)
|
|
{
|
|
}
|
|
|
|
ProfileBlock(string sampleName)
|
|
: this(sampleName, false)
|
|
{
|
|
}
|
|
|
|
public static Regex ProfilePattern
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public static ProfileBlock Start()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public static ProfileBlock Start(string sampleNameFormat, object obj1, object obj2)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Remove the call completely for builds
|
|
public static ProfileBlock Start(string sampleNameFormat, object obj)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Remove the call completely for builds
|
|
public static ProfileBlock Start(string sampleName)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
#endif
|
|
}
|
|
}
|