ProfileAnalyzerExportWindow.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. using UnityEngine;
  2. using System.IO;
  3. using System;
  4. using System.Collections.Generic;
  5. namespace UnityEditor.Performance.ProfileAnalyzer
  6. {
  7. internal class ProfileAnalyzerExportWindow : EditorWindow
  8. {
  9. internal static class Styles
  10. {
  11. public static readonly GUIContent markerTable = new GUIContent("Marker table", "Export data from the single view marker table");
  12. public static readonly GUIContent singleFrameTimes = new GUIContent("Single Frame Times", "Export frame time data from the single view");
  13. public static readonly GUIContent comparisonFrameTimes = new GUIContent("Comparison Frame Times", "Export frame time data from the comparison view");
  14. }
  15. ProfileAnalyzerWindow m_ProfileAnalyzerWindow;
  16. ProfileDataView m_ProfileDataView;
  17. ProfileDataView m_LeftDataView;
  18. ProfileDataView m_RightDataView;
  19. static public ProfileAnalyzerExportWindow FindOpenWindow()
  20. {
  21. UnityEngine.Object[] windows = Resources.FindObjectsOfTypeAll(typeof(ProfileAnalyzerExportWindow));
  22. if (windows != null && windows.Length > 0)
  23. return windows[0] as ProfileAnalyzerExportWindow;
  24. return null;
  25. }
  26. static public bool IsOpen()
  27. {
  28. if (FindOpenWindow() != null)
  29. return true;
  30. return false;
  31. }
  32. static public ProfileAnalyzerExportWindow Open(float screenX, float screenY, ProfileDataView profileSingleView, ProfileDataView profileLeftView, ProfileDataView profileRightView, ProfileAnalyzerWindow profileAnalyzerWindow)
  33. {
  34. ProfileAnalyzerExportWindow window = GetWindow<ProfileAnalyzerExportWindow>("Export");
  35. window.minSize = new Vector2(200, 140);
  36. window.position = new Rect(screenX, screenY, 200, 140);
  37. window.m_ProfileAnalyzerWindow = profileAnalyzerWindow;
  38. window.SetData(profileSingleView, profileLeftView, profileRightView);
  39. window.Show();
  40. return window;
  41. }
  42. static public void CloseAll()
  43. {
  44. ProfileAnalyzerExportWindow window = GetWindow<ProfileAnalyzerExportWindow>("Export");
  45. window.Close();
  46. }
  47. public void SetData(ProfileDataView profileDataView, ProfileDataView leftDataView, ProfileDataView rightDataView)
  48. {
  49. m_ProfileDataView = profileDataView;
  50. m_LeftDataView = leftDataView;
  51. m_RightDataView = rightDataView;
  52. }
  53. void OnGUI()
  54. {
  55. EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true));
  56. GUILayout.Label("Export as CSV:");
  57. GUILayout.Label("");
  58. GUILayout.Label("Single View");
  59. bool enabled = GUI.enabled;
  60. if (m_ProfileDataView == null || !m_ProfileDataView.IsDataValid())
  61. GUI.enabled = false;
  62. if (GUILayout.Button(Styles.markerTable))
  63. SaveMarkerTableCSV();
  64. GUI.enabled = enabled;
  65. if (m_ProfileDataView == null || m_ProfileDataView.analysis == null)
  66. GUI.enabled = false;
  67. if (GUILayout.Button(Styles.singleFrameTimes))
  68. SaveFrameTimesCSV();
  69. GUI.enabled = enabled;
  70. GUILayout.Label("Comparison View");
  71. if (m_LeftDataView == null || !m_LeftDataView.IsDataValid() || m_RightDataView == null || !m_RightDataView.IsDataValid())
  72. GUI.enabled = false;
  73. if (GUILayout.Button(Styles.comparisonFrameTimes))
  74. SaveComparisonFrameTimesCSV();
  75. GUI.enabled = enabled;
  76. EditorGUILayout.EndVertical();
  77. }
  78. void SaveMarkerTableCSV()
  79. {
  80. if (m_ProfileDataView.analysis == null)
  81. return;
  82. string path = EditorUtility.SaveFilePanel("Save marker table CSV data", "", "markerTable.csv", "csv");
  83. if (path.Length != 0)
  84. {
  85. var analytic = ProfileAnalyzerAnalytics.BeginAnalytic();
  86. using (StreamWriter file = new StreamWriter(path))
  87. {
  88. file.Write("Name, ");
  89. file.Write("Median Time, Min Time, Max Time, ");
  90. file.Write("Median Frame Index, Min Frame Index, Max Frame Index, ");
  91. file.Write("Min Depth, Max Depth, ");
  92. file.Write("Total Time, ");
  93. file.Write("Mean Time, Time Lower Quartile, Time Upper Quartile, ");
  94. file.Write("Count Total, Count Median, Count Min, Count Max, ");
  95. file.Write("Number of frames containing Marker, ");
  96. file.Write("First Frame Index, ");
  97. file.Write("Time Min Individual, Time Max Individual, ");
  98. file.Write("Min Individual Frame, Max Individual Frame, ");
  99. file.WriteLine("Time at Median Frame");
  100. List<MarkerData> markerData = m_ProfileDataView.analysis.GetMarkers();
  101. markerData.Sort();
  102. foreach (MarkerData marker in markerData)
  103. {
  104. var markerName = marker.name;
  105. if (markerName.IndexOf('\"') >= 0)
  106. // replace all double quotation marks with single ones to avoid this breaking the escaping with double quotation marks
  107. markerName = markerName.Replace('\"', '\'');
  108. int medianFrameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(marker.medianFrameIndex, m_ProfileDataView);
  109. int minFrameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(marker.minFrameIndex, m_ProfileDataView);
  110. int maxFrameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(marker.maxFrameIndex, m_ProfileDataView);
  111. int firstFrameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(marker.firstFrameIndex, m_ProfileDataView);
  112. int minIndividualFrameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(marker.minIndividualFrameIndex, m_ProfileDataView);
  113. int maxIndividualFrameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(marker.maxIndividualFrameIndex, m_ProfileDataView);
  114. // "Escape" marker names in case it has commas in it.
  115. file.Write("\"{0}\",", markerName);
  116. file.Write("{0},{1},{2},",
  117. marker.msMedian, marker.msMin, marker.msMax);
  118. file.Write("{0},{1},{2},",
  119. medianFrameIndex, minFrameIndex, maxFrameIndex);
  120. file.Write("{0},{1},",
  121. marker.minDepth, marker.maxDepth);
  122. file.Write("{0},",
  123. marker.msTotal);
  124. file.Write("{0},{1},{2},",
  125. marker.msMean, marker.msLowerQuartile, marker.msUpperQuartile);
  126. file.Write("{0},{1},{2},{3},",
  127. marker.count, marker.countMedian, marker.countMin, marker.countMax);
  128. file.Write("{0},", marker.presentOnFrameCount);
  129. file.Write("{0},", firstFrameIndex);
  130. file.Write("{0},{1},",
  131. marker.msMinIndividual, marker.msMaxIndividual);
  132. file.Write("{0},{1},",
  133. minIndividualFrameIndex, maxIndividualFrameIndex);
  134. file.WriteLine("{0}", marker.msAtMedian);
  135. }
  136. }
  137. ProfileAnalyzerAnalytics.SendUIButtonEvent(ProfileAnalyzerAnalytics.UIButton.ExportSingleFrames, analytic);
  138. }
  139. }
  140. void SaveFrameTimesCSV()
  141. {
  142. if (m_ProfileDataView == null)
  143. return;
  144. if (!m_ProfileDataView.IsDataValid())
  145. return;
  146. string path = EditorUtility.SaveFilePanel("Save frame time CSV data", "", "frameTime.csv", "csv");
  147. if (path.Length != 0)
  148. {
  149. var analytic = ProfileAnalyzerAnalytics.BeginAnalytic();
  150. using (StreamWriter file = new StreamWriter(path))
  151. {
  152. file.WriteLine("Frame Offset, Frame Index, Frame Time (ms), Time from first frame (ms)");
  153. float maxFrames = m_ProfileDataView.data.GetFrameCount();
  154. var frame = m_ProfileDataView.data.GetFrame(0);
  155. // msStartTime isn't very accurate so we don't use it
  156. double msTimePassed = 0.0;
  157. for (int frameOffset = 0; frameOffset < maxFrames; frameOffset++)
  158. {
  159. frame = m_ProfileDataView.data.GetFrame(frameOffset);
  160. int frameIndex = m_ProfileDataView.data.OffsetToDisplayFrame(frameOffset);
  161. frameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(frameIndex, m_ProfileDataView);
  162. float msFrame = frame.msFrame;
  163. file.WriteLine("{0},{1},{2},{3}",
  164. frameOffset, frameIndex, msFrame, msTimePassed);
  165. msTimePassed += msFrame;
  166. }
  167. }
  168. ProfileAnalyzerAnalytics.SendUIButtonEvent(ProfileAnalyzerAnalytics.UIButton.ExportSingleFrames, analytic);
  169. }
  170. }
  171. void SaveComparisonFrameTimesCSV()
  172. {
  173. if (m_LeftDataView == null || m_RightDataView == null)
  174. return;
  175. if (!m_LeftDataView.IsDataValid() || !m_RightDataView.IsDataValid())
  176. return;
  177. string path = EditorUtility.SaveFilePanel("Save comparison frame time CSV data", "", "frameTimeComparison.csv", "csv");
  178. if (path.Length != 0)
  179. {
  180. var analytic = ProfileAnalyzerAnalytics.BeginAnalytic();
  181. using (StreamWriter file = new StreamWriter(path))
  182. {
  183. file.Write("Frame Offset, ");
  184. file.Write("Left Frame Index, Right Frame Index, ");
  185. file.Write("Left Frame Time (ms), Left time from first frame (ms), ");
  186. file.Write("Right Frame Time (ms), Right time from first frame (ms), ");
  187. file.WriteLine("Frame Time Diff (ms)");
  188. float maxFrames = Math.Max(m_LeftDataView.data.GetFrameCount(), m_RightDataView.data.GetFrameCount());
  189. var leftFrame = m_LeftDataView.data.GetFrame(0);
  190. var rightFrame = m_RightDataView.data.GetFrame(0);
  191. // msStartTime isn't very accurate so we don't use it
  192. double msTimePassedLeft = 0.0;
  193. double msTimePassedRight = 0.0;
  194. for (int frameOffset = 0; frameOffset < maxFrames; frameOffset++)
  195. {
  196. leftFrame = m_LeftDataView.data.GetFrame(frameOffset);
  197. rightFrame = m_RightDataView.data.GetFrame(frameOffset);
  198. int leftFrameIndex = m_LeftDataView.data.OffsetToDisplayFrame(frameOffset);
  199. leftFrameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(leftFrameIndex, m_LeftDataView);
  200. int rightFrameIndex = m_RightDataView.data.OffsetToDisplayFrame(frameOffset);
  201. rightFrameIndex = m_ProfileAnalyzerWindow.GetRemappedUIFrameIndex(rightFrameIndex, m_RightDataView);
  202. float msFrameLeft = leftFrame != null ? leftFrame.msFrame : 0;
  203. float msFrameRight = rightFrame != null ? rightFrame.msFrame : 0;
  204. float msFrameDiff = msFrameRight - msFrameLeft;
  205. file.Write("{0},", frameOffset);
  206. file.Write("{0},{1},", leftFrameIndex, rightFrameIndex);
  207. file.Write("{0},{1},", msFrameLeft, msTimePassedLeft);
  208. file.Write("{0},{1},", msFrameRight, msTimePassedRight);
  209. file.WriteLine("{0}", msFrameDiff);
  210. msTimePassedLeft += msFrameLeft;
  211. msTimePassedRight += msFrameRight;
  212. }
  213. }
  214. ProfileAnalyzerAnalytics.SendUIButtonEvent(ProfileAnalyzerAnalytics.UIButton.ExportComparisonFrames, analytic);
  215. }
  216. }
  217. }
  218. }