226 lines
7.7 KiB
C#
Raw Normal View History

2023-04-24 15:49:03 +02:00
//Uncomment the next line to enable debugging (also uncomment it in AstarPath.cs)
//#define ProfileAstar //@SHOWINEDITOR
//#define ASTAR_UNITY_PRO_PROFILER //@SHOWINEDITOR Requires ProfileAstar, profiles section of astar code which will show up in the Unity Pro Profiler.
using System.Collections.Generic;
using System;
using UnityEngine;
#if UNITY_5_5_OR_NEWER
using UnityEngine.Profiling;
#endif
namespace Pathfinding {
public class AstarProfiler {
public class ProfilePoint {
//public DateTime lastRecorded;
//public TimeSpan totalTime;
public System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
public int totalCalls;
public long tmpBytes;
public long totalBytes;
}
static readonly Dictionary<string, ProfilePoint> profiles = new Dictionary<string, ProfilePoint>();
static DateTime startTime = DateTime.UtcNow;
public static ProfilePoint[] fastProfiles;
public static string[] fastProfileNames;
private AstarProfiler() {
}
[System.Diagnostics.Conditional("ProfileAstar")]
public static void InitializeFastProfile (string[] profileNames) {
fastProfileNames = new string[profileNames.Length+2];
Array.Copy(profileNames, fastProfileNames, profileNames.Length);
fastProfileNames[fastProfileNames.Length-2] = "__Control1__";
fastProfileNames[fastProfileNames.Length-1] = "__Control2__";
fastProfiles = new ProfilePoint[fastProfileNames.Length];
for (int i = 0; i < fastProfiles.Length; i++) fastProfiles[i] = new ProfilePoint();
}
[System.Diagnostics.Conditional("ProfileAstar")]
public static void StartFastProfile (int tag) {
//profiles.TryGetValue(tag, out point);
fastProfiles[tag].watch.Start();//lastRecorded = DateTime.UtcNow;
}
[System.Diagnostics.Conditional("ProfileAstar")]
public static void EndFastProfile (int tag) {
/*if (!profiles.ContainsKey(tag))
* {
* Debug.LogError("Can only end profiling for a tag which has already been started (tag was " + tag + ")");
* return;
* }*/
ProfilePoint point = fastProfiles[tag];
point.totalCalls++;
point.watch.Stop();
//DateTime now = DateTime.UtcNow;
//point.totalTime += now - point.lastRecorded;
//fastProfiles[tag] = point;
}
[System.Diagnostics.Conditional("ASTAR_UNITY_PRO_PROFILER")]
public static void EndProfile () {
Profiler.EndSample();
}
[System.Diagnostics.Conditional("ProfileAstar")]
public static void StartProfile (string tag) {
#if ASTAR_UNITY_PRO_PROFILER
Profiler.BeginSample(tag);
#else
//Console.WriteLine ("Profile Start - " + tag);
ProfilePoint point;
profiles.TryGetValue(tag, out point);
if (point == null) {
point = new ProfilePoint();
profiles[tag] = point;
}
point.tmpBytes = GC.GetTotalMemory(false);
point.watch.Start();
//point.lastRecorded = DateTime.UtcNow;
//Debug.Log ("Starting " + tag);
#endif
}
[System.Diagnostics.Conditional("ProfileAstar")]
public static void EndProfile (string tag) {
#if !ASTAR_UNITY_PRO_PROFILER
if (!profiles.ContainsKey(tag)) {
Debug.LogError("Can only end profiling for a tag which has already been started (tag was " + tag + ")");
return;
}
//Console.WriteLine ("Profile End - " + tag);
//DateTime now = DateTime.UtcNow;
ProfilePoint point = profiles[tag];
//point.totalTime += now - point.lastRecorded;
++point.totalCalls;
point.watch.Stop();
point.totalBytes += GC.GetTotalMemory(false) - point.tmpBytes;
//profiles[tag] = point;
//Debug.Log ("Ending " + tag);
#else
EndProfile();
#endif
}
[System.Diagnostics.Conditional("ProfileAstar")]
public static void Reset () {
profiles.Clear();
startTime = DateTime.UtcNow;
if (fastProfiles != null) {
for (int i = 0; i < fastProfiles.Length; i++) {
fastProfiles[i] = new ProfilePoint();
}
}
}
[System.Diagnostics.Conditional("ProfileAstar")]
public static void PrintFastResults () {
if (fastProfiles == null)
return;
StartFastProfile(fastProfiles.Length-2);
for (int i = 0; i < 1000; i++) {
StartFastProfile(fastProfiles.Length-1);
EndFastProfile(fastProfiles.Length-1);
}
EndFastProfile(fastProfiles.Length-2);
double avgOverhead = fastProfiles[fastProfiles.Length-2].watch.Elapsed.TotalMilliseconds / 1000.0;
TimeSpan endTime = DateTime.UtcNow - startTime;
var output = new System.Text.StringBuilder();
output.Append("============================\n\t\t\t\tProfile results:\n============================\n");
output.Append("Name | Total Time | Total Calls | Avg/Call | Bytes");
//foreach(KeyValuePair<string, ProfilePoint> pair in profiles)
for (int i = 0; i < fastProfiles.Length; i++) {
string name = fastProfileNames[i];
ProfilePoint value = fastProfiles[i];
int totalCalls = value.totalCalls;
double totalTime = value.watch.Elapsed.TotalMilliseconds - avgOverhead*totalCalls;
if (totalCalls < 1) continue;
output.Append("\n").Append(name.PadLeft(10)).Append("| ");
output.Append(totalTime.ToString("0.0 ").PadLeft(10)).Append(value.watch.Elapsed.TotalMilliseconds.ToString("(0.0)").PadLeft(10)).Append("| ");
output.Append(totalCalls.ToString().PadLeft(10)).Append("| ");
output.Append((totalTime / totalCalls).ToString("0.000").PadLeft(10));
/* output.Append("\nProfile");
* output.Append(name);
* output.Append(" took \t");
* output.Append(totalTime.ToString("0.0"));
* output.Append(" ms to complete over ");
* output.Append(totalCalls);
* output.Append(" iteration");
* if (totalCalls != 1) output.Append("s");
* output.Append(", averaging \t");
* output.Append((totalTime / totalCalls).ToString("0.000"));
* output.Append(" ms per call"); */
}
output.Append("\n\n============================\n\t\tTotal runtime: ");
output.Append(endTime.TotalSeconds.ToString("F3"));
output.Append(" seconds\n============================");
Debug.Log(output.ToString());
}
[System.Diagnostics.Conditional("ProfileAstar")]
public static void PrintResults () {
TimeSpan endTime = DateTime.UtcNow - startTime;
var output = new System.Text.StringBuilder();
output.Append("============================\n\t\t\t\tProfile results:\n============================\n");
int maxLength = 5;
foreach (KeyValuePair<string, ProfilePoint> pair in profiles) {
maxLength = Math.Max(pair.Key.Length, maxLength);
}
output.Append(" Name ".PadRight(maxLength)).
Append("|").Append(" Total Time ".PadRight(20)).
Append("|").Append(" Total Calls ".PadRight(20)).
Append("|").Append(" Avg/Call ".PadRight(20));
foreach (var pair in profiles) {
double totalTime = pair.Value.watch.Elapsed.TotalMilliseconds;
int totalCalls = pair.Value.totalCalls;
if (totalCalls < 1) continue;
string name = pair.Key;
output.Append("\n").Append(name.PadRight(maxLength)).Append("| ");
output.Append(totalTime.ToString("0.0").PadRight(20)).Append("| ");
output.Append(totalCalls.ToString().PadRight(20)).Append("| ");
output.Append((totalTime / totalCalls).ToString("0.000").PadRight(20));
output.Append(AstarMath.FormatBytesBinary((int)pair.Value.totalBytes).PadLeft(10));
/*output.Append("\nProfile ");
* output.Append(pair.Key);
* output.Append(" took ");
* output.Append(totalTime.ToString("0"));
* output.Append(" ms to complete over ");
* output.Append(totalCalls);
* output.Append(" iteration");
* if (totalCalls != 1) output.Append("s");
* output.Append(", averaging ");
* output.Append((totalTime / totalCalls).ToString("0.0"));
* output.Append(" ms per call");*/
}
output.Append("\n\n============================\n\t\tTotal runtime: ");
output.Append(endTime.TotalSeconds.ToString("F3"));
output.Append(" seconds\n============================");
Debug.Log(output.ToString());
}
}
}