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

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
}
}