Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EngineProfilerInspector.cs 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine;
  5. //This profiler is based on the Entitas Visual Debugging tool
  6. //https://github.com/sschmid/Entitas-CSharp
  7. namespace Svelto.ECS.Profiler
  8. {
  9. [CustomEditor(typeof (EngineProfilerBehaviour))]
  10. public class EngineProfilerInspector : Editor
  11. {
  12. enum SORTING_OPTIONS
  13. {
  14. AVERAGE,
  15. MIN,
  16. MAX,
  17. NAME,
  18. NONE
  19. }
  20. static bool _hideEmptyEngines = true;
  21. static bool _showTickEngines;
  22. static bool _showAddEngines;
  23. static bool _showRemoveEngines;
  24. static string _systemNameSearchTerm = string.Empty;
  25. float _axisUpperBounds = 2f;
  26. string updateTitle = "Update".PadRight(15, ' ');
  27. string lateUpdateTitle = "Late".PadRight(13, ' ');
  28. string fixedupdateTitle = "Fixed".PadRight(15, ' ');
  29. string minTitle = "Min".PadRight(15, ' ');
  30. string maxTitle = "Max".PadRight(15, ' ');
  31. string avgTitle = "Avg".PadRight(15, ' ');
  32. EnginesMonitor _enginesMonitor;
  33. Queue<float> _engineMonitorData;
  34. const int SYSTEM_MONITOR_DATA_LENGTH = 300;
  35. SORTING_OPTIONS _sortingOption = SORTING_OPTIONS.AVERAGE;
  36. public override void OnInspectorGUI()
  37. {
  38. var engineProfilerBehaviour = (EngineProfilerBehaviour) target;
  39. EngineInfo[] engines = new EngineInfo[engineProfilerBehaviour.engines.Count];
  40. engineProfilerBehaviour.engines.CopyTo(engines, 0);
  41. DrawEngineList(engineProfilerBehaviour, engines);
  42. EditorUtility.SetDirty(target);
  43. }
  44. void DrawEngineList(EngineProfilerBehaviour engineProfilerBehaviour, EngineInfo[] engines)
  45. {
  46. ProfilerEditorLayout.BeginVerticalBox();
  47. {
  48. ProfilerEditorLayout.BeginHorizontal();
  49. {
  50. if (GUILayout.Button("Reset Durations", GUILayout.Width(120), GUILayout.Height(14)))
  51. {
  52. engineProfilerBehaviour.ResetDurations();
  53. }
  54. }
  55. ProfilerEditorLayout.EndHorizontal();
  56. _sortingOption = (SORTING_OPTIONS) EditorGUILayout.EnumPopup("Sort By:", _sortingOption);
  57. _hideEmptyEngines = EditorGUILayout.Toggle("Hide empty systems", _hideEmptyEngines);
  58. EditorGUILayout.Space();
  59. ProfilerEditorLayout.BeginHorizontal();
  60. {
  61. _systemNameSearchTerm = EditorGUILayout.TextField("Search", _systemNameSearchTerm);
  62. const string clearButtonControlName = "Clear Button";
  63. GUI.SetNextControlName(clearButtonControlName);
  64. if (GUILayout.Button("x", GUILayout.Width(19), GUILayout.Height(14)))
  65. {
  66. _systemNameSearchTerm = string.Empty;
  67. GUI.FocusControl(clearButtonControlName);
  68. }
  69. }
  70. ProfilerEditorLayout.EndHorizontal();
  71. _showAddEngines = EditorGUILayout.Foldout(_showAddEngines, "Engines Add");
  72. if (_showAddEngines && ShouldShowSystems(engines))
  73. {
  74. ProfilerEditorLayout.BeginVerticalBox();
  75. {
  76. var systemsDrawn = DrawAddEngineInfos(engines);
  77. if (systemsDrawn == 0)
  78. {
  79. EditorGUILayout.LabelField(string.Empty);
  80. }
  81. }
  82. ProfilerEditorLayout.EndVertical();
  83. }
  84. _showRemoveEngines = EditorGUILayout.Foldout(_showRemoveEngines, "Engines Remove");
  85. if (_showRemoveEngines && ShouldShowSystems(engines))
  86. {
  87. ProfilerEditorLayout.BeginVerticalBox();
  88. {
  89. var systemsDrawn = DrawRemoveEngineInfos(engines);
  90. if (systemsDrawn == 0)
  91. {
  92. EditorGUILayout.LabelField(string.Empty);
  93. }
  94. }
  95. ProfilerEditorLayout.EndVertical();
  96. }
  97. }
  98. ProfilerEditorLayout.EndVertical();
  99. }
  100. int DrawAddEngineInfos(EngineInfo[] engines)
  101. {
  102. if (_sortingOption != SORTING_OPTIONS.NONE)
  103. {
  104. SortAddEngines(engines);
  105. }
  106. string title = avgTitle.FastConcat(minTitle).FastConcat(maxTitle);
  107. EditorGUILayout.LabelField("Engine Name", title, EditorStyles.boldLabel);
  108. int enginesDrawn = 0;
  109. for (int i = 0; i < engines.Length; i++)
  110. {
  111. EngineInfo engineInfo = engines[i];
  112. if (engineInfo.engineName.ToLower().Contains(_systemNameSearchTerm.ToLower()) &&
  113. !engineInfo.minAddDuration.Equals(0) && !engineInfo.maxAddDuration.Equals(0))
  114. {
  115. ProfilerEditorLayout.BeginHorizontal();
  116. {
  117. var avg = string.Format("{0:0.000}", engineInfo.averageAddDuration).PadRight(15);
  118. var min = string.Format("{0:0.000}", engineInfo.minAddDuration).PadRight(15);
  119. var max = string.Format("{0:0.000}", engineInfo.maxAddDuration);
  120. string output = avg.FastConcat(min).FastConcat(max);
  121. EditorGUILayout.LabelField(engineInfo.engineName, output, GetEngineStyle());
  122. }
  123. ProfilerEditorLayout.EndHorizontal();
  124. enginesDrawn += 1;
  125. }
  126. }
  127. return enginesDrawn;
  128. }
  129. int DrawRemoveEngineInfos(EngineInfo[] engines)
  130. {
  131. if (_sortingOption != SORTING_OPTIONS.NONE)
  132. {
  133. SortRemoveEngines(engines);
  134. }
  135. string title = avgTitle.FastConcat(minTitle).FastConcat(maxTitle);
  136. EditorGUILayout.LabelField("Engine Name", title, EditorStyles.boldLabel);
  137. int enginesDrawn = 0;
  138. for (int i = 0; i < engines.Length; i++)
  139. {
  140. EngineInfo engineInfo = engines[i];
  141. if (engineInfo.engineName.ToLower().Contains(_systemNameSearchTerm.ToLower()) &&
  142. !engineInfo.minRemoveDuration.Equals(0) && !engineInfo.maxRemoveDuration.Equals(0))
  143. {
  144. ProfilerEditorLayout.BeginHorizontal();
  145. {
  146. var avg = string.Format("{0:0.000}", engineInfo.averageRemoveDuration).PadRight(15);
  147. var min = string.Format("{0:0.000}", engineInfo.minRemoveDuration).PadRight(15);
  148. var max = string.Format("{0:0.000}", engineInfo.maxRemoveDuration);
  149. string output = avg.FastConcat(min).FastConcat(max);
  150. EditorGUILayout.LabelField(engineInfo.engineName, output, GetEngineStyle());
  151. }
  152. ProfilerEditorLayout.EndHorizontal();
  153. enginesDrawn += 1;
  154. }
  155. }
  156. return enginesDrawn;
  157. }
  158. static GUIStyle GetEngineStyle()
  159. {
  160. var style = new GUIStyle(GUI.skin.label);
  161. var color = EditorGUIUtility.isProSkin ? Color.white : style.normal.textColor;
  162. style.normal.textColor = color;
  163. return style;
  164. }
  165. static bool ShouldShowSystems(EngineInfo[] engines)
  166. {
  167. return engines.Length > 0;
  168. }
  169. #region Sorting Engines
  170. void SortAddEngines(EngineInfo[] engines)
  171. {
  172. switch (_sortingOption)
  173. {
  174. case SORTING_OPTIONS.AVERAGE:
  175. Array.Sort(engines,
  176. (engine1, engine2) => engine2.averageAddDuration.CompareTo(engine1.averageAddDuration));
  177. break;
  178. case SORTING_OPTIONS.MIN:
  179. Array.Sort(engines,
  180. (engine1, engine2) => engine2.minAddDuration.CompareTo(engine1.minAddDuration));
  181. break;
  182. case SORTING_OPTIONS.MAX:
  183. Array.Sort(engines,
  184. (engine1, engine2) => engine2.maxAddDuration.CompareTo(engine1.maxAddDuration));
  185. break;
  186. case SORTING_OPTIONS.NAME:
  187. Array.Sort(engines,
  188. (engine1, engine2) => String.Compare(engine1.engineName, engine2.engineName, StringComparison.Ordinal));
  189. break;
  190. }
  191. }
  192. void SortRemoveEngines(EngineInfo[] engines)
  193. {
  194. switch (_sortingOption)
  195. {
  196. case SORTING_OPTIONS.AVERAGE:
  197. Array.Sort(engines,
  198. (engine1, engine2) => engine2.averageRemoveDuration.CompareTo(engine1.averageRemoveDuration));
  199. break;
  200. case SORTING_OPTIONS.MIN:
  201. Array.Sort(engines,
  202. (engine1, engine2) => engine2.minRemoveDuration.CompareTo(engine1.minRemoveDuration));
  203. break;
  204. case SORTING_OPTIONS.MAX:
  205. Array.Sort(engines,
  206. (engine1, engine2) => engine2.maxRemoveDuration.CompareTo(engine1.maxRemoveDuration));
  207. break;
  208. case SORTING_OPTIONS.NAME:
  209. Array.Sort(engines,
  210. (engine1, engine2) => String.Compare(engine1.engineName, engine2.engineName, StringComparison.Ordinal));
  211. break;
  212. }
  213. }
  214. }
  215. #endregion
  216. }