@@ -894,7 +894,7 @@ private IProcessForStackSource GetProcessFromStack(StackSourceCallStackIndex cal
894894 if ( caller == StackSourceCallStackIndex . Invalid )
895895 {
896896 string topCallStackStr = stackSource . GetFrameName ( stackSource . GetFrameIndex ( callStack ) , true ) ;
897-
897+
898898 if ( GetProcessForStackSourceFromTopCallStackFrame ( topCallStackStr , out ret ) )
899899 {
900900 processes . Add ( ret ) ;
@@ -1063,80 +1063,11 @@ public override void Open(Window parentWindow, StatusBar worker, Action doAfter)
10631063 {
10641064 if ( Viewer == null )
10651065 {
1066- var etlDataFile = DataFile as ETLPerfViewData ;
1067- TraceLog trace = null ;
1068- if ( etlDataFile != null )
1069- {
1070- trace = etlDataFile . GetTraceLog ( worker . LogWriter ) ;
1071- }
1072- else
1073- {
1074- var linuxDataFile = DataFile as LinuxPerfViewData ;
1075- if ( linuxDataFile != null )
1076- {
1077- trace = linuxDataFile . GetTraceLog ( worker . LogWriter ) ;
1078- }
1079- else
1080- {
1081- var eventPipeDataFile = DataFile as EventPipePerfViewData ;
1082- if ( eventPipeDataFile != null )
1083- {
1084- trace = eventPipeDataFile . GetTraceLog ( worker . LogWriter ) ;
1085- }
1086- }
1087- }
1066+ TraceLog trace = GetTrace ( worker ) ;
10881067
10891068 worker . StartWork ( "Opening " + Name , delegate ( )
10901069 {
1091- var reportFileName = CacheFiles . FindFile ( FilePath , "." + Name + ".html" ) ;
1092- using ( var writer = File . CreateText ( reportFileName ) )
1093- {
1094- writer . WriteLine ( "<html>" ) ;
1095- writer . WriteLine ( "<head>" ) ;
1096- writer . WriteLine ( "<title>{0}</title>" , Title ) ;
1097- writer . WriteLine ( "<meta charset=\" UTF-8\" />" ) ;
1098- writer . WriteLine ( "<meta http-equiv=\" X-UA-Compatible\" content=\" IE=edge\" />" ) ;
1099-
1100- // Add basic styling to the generated HTML
1101- writer . WriteLine ( @"
1102- <style>
1103- body {
1104- font-family: Segoe UI Light, Helvetica, sans-serif;
1105- }
1106-
1107- tr:hover {
1108- background-color: #eeeeee;
1109- }
1110-
1111- th {
1112- background-color: #eeeeee;
1113- font-family: Helvetica;
1114- padding: 4px;
1115- font-size: small;
1116- font-weight: normal;
1117- }
1118-
1119- td {
1120- font-family: Consolas, monospace;
1121- font-size: small;
1122- padding: 3px;
1123- padding-bottom: 5px;
1124- }
1125-
1126- table {
1127- border-collapse: collapse;
1128- }
1129- </style>
1130- " ) ;
1131-
1132- writer . WriteLine ( "</head>" ) ;
1133- writer . WriteLine ( "<body>" ) ;
1134- WriteHtmlBody ( trace , writer , reportFileName , worker . LogWriter ) ;
1135- writer . WriteLine ( "</body>" ) ;
1136- writer . WriteLine ( "</html>" ) ;
1137-
1138-
1139- }
1070+ string reportFileName = GenerateReportFile ( worker , trace ) ;
11401071
11411072 worker . EndWork ( delegate ( )
11421073 {
@@ -1185,8 +1116,110 @@ public override void Open(Window parentWindow, StatusBar worker, Action doAfter)
11851116 }
11861117 }
11871118
1119+ /// <summary>
1120+ /// Generates an HTML report and opens it using the machine's default handler .html file paths.
1121+ /// </summary>
1122+ /// <param name="worker">The StatusBar that should be updated with progress.</param>
1123+ public void OpenInExternalBrowser ( StatusBar worker )
1124+ {
1125+ TraceLog trace = GetTrace ( worker ) ;
1126+
1127+ worker . StartWork ( "Opening in external browser " + Name , delegate ( )
1128+ {
1129+ string reportFileName = GenerateReportFile ( worker , trace ) ;
1130+
1131+ worker . EndWork ( delegate ( )
1132+ {
1133+ Process . Start ( reportFileName ) ;
1134+ } ) ;
1135+ } ) ;
1136+ }
1137+
11881138 public override void Close ( ) { }
11891139 public override ImageSource Icon { get { return GuiApp . MainWindow . Resources [ "HtmlReportBitmapImage" ] as ImageSource ; } }
1140+
1141+ private TraceLog GetTrace ( StatusBar worker )
1142+ {
1143+ var etlDataFile = DataFile as ETLPerfViewData ;
1144+ TraceLog trace = null ;
1145+ if ( etlDataFile != null )
1146+ {
1147+ trace = etlDataFile . GetTraceLog ( worker . LogWriter ) ;
1148+ }
1149+ else
1150+ {
1151+ var linuxDataFile = DataFile as LinuxPerfViewData ;
1152+ if ( linuxDataFile != null )
1153+ {
1154+ trace = linuxDataFile . GetTraceLog ( worker . LogWriter ) ;
1155+ }
1156+ else
1157+ {
1158+ var eventPipeDataFile = DataFile as EventPipePerfViewData ;
1159+ if ( eventPipeDataFile != null )
1160+ {
1161+ trace = eventPipeDataFile . GetTraceLog ( worker . LogWriter ) ;
1162+ }
1163+ }
1164+ }
1165+
1166+ return trace ;
1167+ }
1168+
1169+ private string GenerateReportFile ( StatusBar worker , TraceLog trace )
1170+ {
1171+ var reportFileName = CacheFiles . FindFile ( FilePath , "." + Name + ".html" ) ;
1172+ using ( var writer = File . CreateText ( reportFileName ) )
1173+ {
1174+ writer . WriteLine ( "<html>" ) ;
1175+ writer . WriteLine ( "<head>" ) ;
1176+ writer . WriteLine ( "<title>{0}</title>" , Title ) ;
1177+ writer . WriteLine ( "<meta charset=\" UTF-8\" />" ) ;
1178+ writer . WriteLine ( "<meta http-equiv=\" X-UA-Compatible\" content=\" IE=edge\" />" ) ;
1179+
1180+ // Add basic styling to the generated HTML
1181+ writer . WriteLine ( @"
1182+ <style>
1183+ body {
1184+ font-family: Segoe UI Light, Helvetica, sans-serif;
1185+ }
1186+
1187+ tr:hover {
1188+ background-color: #eeeeee;
1189+ }
1190+
1191+ th {
1192+ background-color: #eeeeee;
1193+ font-family: Helvetica;
1194+ padding: 4px;
1195+ font-size: small;
1196+ font-weight: normal;
1197+ }
1198+
1199+ td {
1200+ font-family: Consolas, monospace;
1201+ font-size: small;
1202+ padding: 3px;
1203+ padding-bottom: 5px;
1204+ }
1205+
1206+ table {
1207+ border-collapse: collapse;
1208+ }
1209+ </style>
1210+ " ) ;
1211+
1212+ writer . WriteLine ( "</head>" ) ;
1213+ writer . WriteLine ( "<body>" ) ;
1214+ WriteHtmlBody ( trace , writer , reportFileName , worker . LogWriter ) ;
1215+ writer . WriteLine ( "</body>" ) ;
1216+ writer . WriteLine ( "</html>" ) ;
1217+
1218+
1219+ }
1220+
1221+ return reportFileName ;
1222+ }
11901223 }
11911224
11921225 public class PerfViewTraceInfo : PerfViewHtmlReport
@@ -6705,7 +6738,7 @@ protected internal override void ConfigureStackWindow(string stackSourceName, St
67056738 {
67066739 if ( App . ConfigData [ "WarnedAboutOsHeapAllocTypes" ] == null )
67076740 {
6708- MessageBox . Show ( stackWindow ,
6741+ MessageBox . Show ( stackWindow ,
67096742 "Warning: Allocation type resolution only happens on window launch.\r \n " +
67106743 "Thus if you manually lookup symbols in this view you will get method\r \n " +
67116744 "names of allocations sites, but to get the type name associated the \r \n " +
@@ -8766,18 +8799,18 @@ protected internal override StackSource OpenStackSourceImpl(string streamName, T
87668799 {
87678800 sample . Metric = objInfo . RepresentativeSize ;
87688801 sample . Count = objInfo . RepresentativeSize / objInfo . Size ; // We guess a count from the size.
8769- sample . TimeRelativeMSec = objInfo . AllocationTimeRelativeMSec ;
8802+ sample . TimeRelativeMSec = objInfo . AllocationTimeRelativeMSec ;
87708803 sample . StackIndex = stackSource . Interner . CallStackIntern ( objInfo . ClassFrame , objInfo . AllocStack ) ; // Add the type as a pseudo frame.
8771- stackSource . AddSample ( sample ) ;
8804+ stackSource . AddSample ( sample ) ;
87728805 return true ;
87738806 } ;
87748807 newHeap . OnObjectDestroy += delegate ( double time , int gen , Address objAddress , GCHeapSimulatorObject objInfo )
87758808 {
87768809 sample . Metric = - objInfo . RepresentativeSize ;
87778810 sample . Count = - ( objInfo . RepresentativeSize / objInfo . Size ) ; // We guess a count from the size.
8778- sample . TimeRelativeMSec = time ;
8811+ sample . TimeRelativeMSec = time ;
87798812 sample . StackIndex = stackSource . Interner . CallStackIntern ( objInfo . ClassFrame , objInfo . AllocStack ) ; // We remove the same stack we added at alloc.
8780- stackSource . AddSample ( sample ) ;
8813+ stackSource . AddSample ( sample ) ;
87818814 } ;
87828815
87838816 newHeap . OnGC += delegate ( double time , int gen )
@@ -8812,7 +8845,7 @@ protected internal override StackSource OpenStackSourceImpl(string streamName, T
88128845 {
88138846 sample . Metric = objInfo . RepresentativeSize ;
88148847 sample . Count = ( objInfo . RepresentativeSize / objInfo . Size ) ; // We guess a count from the size.
8815- sample . TimeRelativeMSec = objInfo . AllocationTimeRelativeMSec ;
8848+ sample . TimeRelativeMSec = objInfo . AllocationTimeRelativeMSec ;
88168849 sample . StackIndex = stackSource . Interner . CallStackIntern ( objInfo . ClassFrame , objInfo . AllocStack ) ;
88178850 stackSource . AddSample ( sample ) ;
88188851 }
@@ -8848,12 +8881,12 @@ protected internal override StackSource OpenStackSourceImpl(string streamName, T
88488881 var typeName = data . TypeName ;
88498882 if ( string . IsNullOrEmpty ( typeName ) )
88508883 {
8851- // Attempt to resolve the type name.
8852- TraceLoadedModule module = data . Process ( ) . LoadedModules . GetModuleContainingAddress ( data . TypeID , data . TimeStampRelativeMSec ) ;
8884+ // Attempt to resolve the type name.
8885+ TraceLoadedModule module = data . Process ( ) . LoadedModules . GetModuleContainingAddress ( data . TypeID , data . TimeStampRelativeMSec ) ;
88538886 if ( module != null )
88548887 {
8855- // Resolve the type name.
8856- typeName = typeNameSymbolResolver . ResolveTypeName ( ( int ) ( data . TypeID - module . ModuleFile . ImageBase ) , module . ModuleFile , TypeNameSymbolResolver . TypeNameOptions . StripModuleName ) ;
8888+ // Resolve the type name.
8889+ typeName = typeNameSymbolResolver . ResolveTypeName ( ( int ) ( data . TypeID - module . ModuleFile . ImageBase ) , module . ModuleFile , TypeNameSymbolResolver . TypeNameOptions . StripModuleName ) ;
88578890 }
88588891 }
88598892
@@ -8912,7 +8945,7 @@ protected internal override void ConfigureStackWindow(string stackSourceName, St
89128945 stackWindow . ComputeMaxInTopStats = true ;
89138946 }
89148947
8915- if ( m_extraTopStats != null )
8948+ if ( m_extraTopStats != null )
89168949 {
89178950 stackWindow . ExtraTopStats += " " + m_extraTopStats ;
89188951 }
0 commit comments