Skip to content

Instantly share code, notes, and snippets.

@noisecrime
Created September 10, 2017 10:31
Show Gist options
  • Save noisecrime/493d2cdb549286b5298984bc0f95f129 to your computer and use it in GitHub Desktop.
Save noisecrime/493d2cdb549286b5298984bc0f95f129 to your computer and use it in GitHub Desktop.
StopWatchProfiler
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
#if UNITY_5_5_OR_NEWER
using Profiler = UnityEngine.Profiling.Profiler;
#endif
public class StopWatchProfiler : MonoBehaviour
{
public struct ProfilerMemoryPacket
{
public long monoHeap;
public long monoUsed;
public long memoryAllocated;
public long memoryReserved;
}
public class ProfilerPacket
{
public long startTime;
public long totalTime;
public int totalCalls;
public ProfilerMemoryPacket memoryOnEnter;
public ProfilerMemoryPacket memoryOnExit;
}
public static Dictionary<string, ProfilerPacket> m_PofilerPackets = new Dictionary<string, ProfilerPacket>();
public static List<string> m_FiLoWatchnames = new List<string>();
public static Stopwatch m_Stopwatch = new Stopwatch();
public static int m_HasMatchngPairs = 0;
void Start()
{
StartCoroutine( EndOfFrame() );
}
IEnumerator EndOfFrame()
{
while ( true )
{
NewFrame();
yield return new WaitForEndOfFrame();
}
}
#region ENTRY POINTS
// Called from scripts to begin or end both custom stopwatch profiling and Unity Profiling.
[Conditional( "DEVELOPMENT_BUILD" ), Conditional( "UNITY_EDITOR" )]
public static void BeginSample( string name )
{
BeginWatch(name);
Profiler.BeginSample(name);
}
[Conditional( "DEVELOPMENT_BUILD" ), Conditional( "UNITY_EDITOR" )]
public static void EndSample()
{
EndWatch();
Profiler.EndSample();
}
#endregion
[Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
private static void NewFrame()
{
if(m_HasMatchngPairs != 0) UnityEngine.Debug.LogError("StopWatchProfiler: A Begin has no matching End");
m_PofilerPackets.Clear();
m_FiLoWatchnames.Clear();
m_Stopwatch.Reset();
m_Stopwatch.Start();
m_HasMatchngPairs = 0;
}
[Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
private static void BeginWatch( string name )
{
ProfilerPacket pp;
if ( m_PofilerPackets.TryGetValue( name, out pp ) == false )
{
pp = new ProfilerPacket();
m_PofilerPackets.Add( name, pp);
}
pp.startTime = m_Stopwatch.ElapsedMilliseconds;
#if UNITY_5_5_OR_NEWER
pp.memoryOnEnter.monoHeap = Profiler.GetMonoHeapSizeLong(); // reserved system memory that Mono is using for allocations
pp.memoryOnEnter.monoUsed = Profiler.GetMonoUsedSizeLong(); // amount of allocated memory for non collected objects in Mono
pp.memoryOnEnter.memoryAllocated = Profiler.GetTotalAllocatedMemoryLong(); // amount of allocated and used system memory
pp.memoryOnEnter.memoryReserved = Profiler.GetTotalReservedMemoryLong(); // amount of reserved system memory
// pp.memoryOnEnter.memTexture = Profiler.GetRuntimeMemorySize(); // runtime memory usage of the resource
#else
pp.memoryOnEnter.monoHeap = Profiler.GetMonoHeapSize(); // reserved system memory that Mono is using for allocations
pp.memoryOnEnter.monoUsed = Profiler.GetMonoUsedSize(); // amount of allocated memory for non collected objects in Mono
pp.memoryOnEnter.memoryAllocated = Profiler.GetTotalAllocatedMemory(); // amount of allocated and used system memory
pp.memoryOnEnter.memoryReserved = Profiler.GetTotalReservedMemory(); // amount of reserved system memory
#endif
m_FiLoWatchnames.Add( name );
m_HasMatchngPairs++;
// UnityEngine.Debug.LogFormat( "BeginWatch: {0} Time: {1} Calls: {2}", name, pp.startTime, pp.totalCalls);
}
[Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
private static void EndWatch()
{
m_HasMatchngPairs--;
if ( m_FiLoWatchnames.Count - 1 < 0 )
{
UnityEngine.Debug.LogError( "StopWatchProfiler: End has no Begin!" );
return;
}
string name = m_FiLoWatchnames[ m_FiLoWatchnames.Count - 1];
ProfilerPacket pp;
if ( m_PofilerPackets.TryGetValue( name, out pp ) == true )
{
pp.totalTime += m_Stopwatch.ElapsedMilliseconds - pp.startTime;
pp.totalCalls += 1;
#if UNITY_5_5_OR_NEWER
pp.memoryOnExit.monoHeap = Profiler.GetMonoHeapSizeLong(); // reserved system memory that Mono is using for allocations
pp.memoryOnExit.monoUsed = Profiler.GetMonoUsedSizeLong(); // amount of allocated memory for non collected objects in Mono
pp.memoryOnExit.memoryAllocated = Profiler.GetTotalAllocatedMemoryLong(); // amount of allocated and used system memory
pp.memoryOnExit.memoryReserved = Profiler.GetTotalReservedMemoryLong(); // amount of reserved system memory
// pp.memoryOnEnter.memTexture = Profiler.GetRuntimeMemorySize(); // runtime memory usage of the resource
#else
pp.memoryOnExit.monoHeap = Profiler.GetMonoHeapSize(); // reserved system memory that Mono is using for allocations
pp.memoryOnExit.monoUsed = Profiler.GetMonoUsedSize(); // amount of allocated memory for non collected objects in Mono
pp.memoryOnExit.memoryAllocated = Profiler.GetTotalAllocatedMemory(); // amount of allocated and used system memory
pp.memoryOnExit.memoryReserved = Profiler.GetTotalReservedMemory(); // amount of reserved system memory
#endif
// UnityEngine.Debug.LogFormat( "EndWatch: {0} Time: {1} Calls: {2}", name, pp.totalTime, pp.totalCalls);
}
m_FiLoWatchnames.RemoveAt(m_FiLoWatchnames.Count - 1);
}
#if DEVELOPMENT_BUILD || UNITY_EDITOR
// "{0} Ms: {1:d4} Calls: {2:d2} Heap: {3}/{4} Used: {5}/{6} Allocated: {7}/{8} Reserved: {9}/{10}\n")
public static string GetResults( string format = "{0} Ms: {1:d4} Calls: {2:d2} Mem: {5,4:F1}/{6,4:F1}\n")
{
m_Stopwatch.Stop();
// if( !UnityEngine.Debug.isDebugBuild ) return "NOT DEVELOPMENT BUILD";
if( m_HasMatchngPairs != 0) UnityEngine.Debug.LogError("StopWatchProfiler: A Begin has no matching End");
if( m_PofilerPackets.Count == 0) return ( "No Results");
string str = "";
double bytesToMegaBytes = 1024.0 * 1024.0;
foreach (KeyValuePair<string, ProfilerPacket> pair in m_PofilerPackets)
{
double deltaHeap = ( (long) pair.Value.memoryOnExit.monoHeap - (long) pair.Value.memoryOnEnter.monoHeap);
double deltaUsed = ( (long) pair.Value.memoryOnExit.monoUsed - (long) pair.Value.memoryOnEnter.monoUsed);
double deltaAllocated = ( (long) pair.Value.memoryOnExit.memoryAllocated - (long) pair.Value.memoryOnEnter.memoryAllocated);
double deltaReserved = ( (long) pair.Value.memoryOnExit.memoryReserved - (long) pair.Value.memoryOnEnter.memoryReserved);
str += string.Format
(
format,
pair.Key, pair.Value.totalTime/pair.Value.totalCalls, pair.Value.totalCalls,
deltaHeap/bytesToMegaBytes, pair.Value.memoryOnExit.monoHeap/bytesToMegaBytes,
deltaUsed/bytesToMegaBytes, pair.Value.memoryOnExit.monoUsed/bytesToMegaBytes,
deltaAllocated/bytesToMegaBytes, pair.Value.memoryOnExit.memoryAllocated/bytesToMegaBytes,
deltaReserved/bytesToMegaBytes, pair.Value.memoryOnExit.memoryReserved/bytesToMegaBytes
);
}
return str;
}
#else
public static string GetResults()
{
return "NOT DEVELOPMENT BUILD";
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment