@@ -430,7 +430,7 @@ public void Start(CommandLineArgs parsedArgs)
430430 LogFile . WriteLine ( "[Kernel Log: {0}]" , Path . GetFullPath ( kernelFileName ) ) ;
431431 }
432432
433- using ( TraceEventSession kernelModeSession = new TraceEventSession ( KernelTraceEventParser . KernelSessionName , kernelFileName ) )
433+ using ( TraceEventSession kernelModeSession = new TraceEventSession ( s_KernelessionName , kernelFileName ) )
434434 {
435435 if ( parsedArgs . CpuCounters != null )
436436 {
@@ -540,7 +540,7 @@ public void Start(CommandLineArgs parsedArgs)
540540 PerfViewLogger . Log . StartTracing ( ) ;
541541 PerfViewLogger . StartTime = DateTime . UtcNow ;
542542
543- PerfViewLogger . Log . SessionParameters ( KernelTraceEventParser . KernelSessionName , kernelFileName ?? "" ,
543+ PerfViewLogger . Log . SessionParameters ( s_KernelessionName , kernelFileName ?? "" ,
544544 kernelModeSession . BufferSizeMB , kernelModeSession . CircularBufferMB ) ;
545545 PerfViewLogger . Log . KernelEnableParameters ( parsedArgs . KernelEvents , parsedArgs . KernelEvents ) ;
546546 PerfViewLogger . Log . SessionParameters ( s_UserModeSessionName , userFileName ?? "" ,
@@ -1109,7 +1109,7 @@ public void Stop(CommandLineArgs parsedArgs)
11091109
11101110 }
11111111
1112- LogFile . WriteLine ( "Stopping tracing for sessions '" + KernelTraceEventParser . KernelSessionName +
1112+ LogFile . WriteLine ( "Stopping tracing for sessions '" + s_KernelessionName +
11131113 "' and '" + s_UserModeSessionName + "'." ) ;
11141114
11151115 PerfViewLogger . Log . CommandLineParameters ( ParsedArgsAsString ( null , parsedArgs ) , Environment . CurrentDirectory , AppLog . VersionNumber ) ;
@@ -1135,70 +1135,91 @@ public void Stop(CommandLineArgs parsedArgs)
11351135 }
11361136
11371137 // Try to stop the kernel session
1138- try
1138+
1139+ Task stopKernel = Task . Factory . StartNew ( delegate ( )
11391140 {
1140- if ( parsedArgs . KernelEvents != KernelTraceEventParser . Keywords . None )
1141+ try
11411142 {
1142- using ( var kernelSession = new TraceEventSession ( KernelTraceEventParser . KernelSessionName , TraceEventSessionOptions . Attach ) )
1143+ if ( parsedArgs . KernelEvents != KernelTraceEventParser . Keywords . None )
11431144 {
1144- if ( parsedArgs . InMemoryCircularBuffer )
1145+ using ( var kernelSession = new TraceEventSession ( s_KernelessionName , TraceEventSessionOptions . Attach ) )
11451146 {
1146- kernelSession . SetFileName ( Path . ChangeExtension ( parsedArgs . DataFile , ".kernel.etl" ) ) ; // Flush the file
1147-
1148- // We need to manually do a kernel rundown to get the list of running processes and images loaded into memory
1149- // Ideally this is done by the SetFileName API so we can avoid merging.
1150- var rundownFile = Path . ChangeExtension ( parsedArgs . DataFile , ".kernelRundown.etl" ) ;
1151-
1152- // Note that enabling providers is async, and thus there is a concern that we would lose events if we don't wait
1153- // until the events are logged before shutting down the session. However we only need the DCEnd events and
1154- // those are PART of kernel session stop, which is synchronous (the session will not die until it is complete)
1155- // so we don't have to wait after enabling the kernel session. It is somewhat unfortunate that we have both
1156- // the DCStart and the DCStop events, but there does not seem to be a way of asking for just one set.
1157- using ( var kernelRundownSession = new TraceEventSession ( s_UserModeSessionName + "Rundown" , rundownFile ) )
1147+ if ( parsedArgs . InMemoryCircularBuffer )
11581148 {
1159- kernelRundownSession . BufferSizeMB = 256 ; // Try to avoid lost events.
1160- kernelRundownSession . EnableKernelProvider ( KernelTraceEventParser . Keywords . Process | KernelTraceEventParser . Keywords . ImageLoad ) ;
1149+ LogFile . WriteLine ( "InMemoryCircularBuffer Set, Dumping kernel log" ) ;
1150+ kernelSession . SetFileName ( Path . ChangeExtension ( parsedArgs . DataFile , ".kernel.etl" ) ) ; // Flush the file
1151+
1152+
1153+ LogFile . WriteLine ( "InMemoryCircularBuffer Set, Doing Kernel Rundown" ) ;
1154+ // We need to manually do a kernel rundown to get the list of running processes and images loaded into memory
1155+ // Ideally this is done by the SetFileName API so we can avoid merging.
1156+ var rundownFile = Path . ChangeExtension ( parsedArgs . DataFile , ".kernelRundown.etl" ) ;
1157+
1158+ // Note that enabling providers is async, and thus there is a concern that we would lose events if we don't wait
1159+ // until the events are logged before shutting down the session. However we only need the DCEnd events and
1160+ // those are PART of kernel session stop, which is synchronous (the session will not die until it is complete)
1161+ // so we don't have to wait after enabling the kernel session. It is somewhat unfortunate that we have both
1162+ // the DCStart and the DCStop events, but there does not seem to be a way of asking for just one set.
1163+ using ( var kernelRundownSession = new TraceEventSession ( s_UserModeSessionName + "KernelRundown" , rundownFile ) )
1164+ {
1165+ kernelRundownSession . BufferSizeMB = 256 ; // Try to avoid lost events.
1166+ kernelRundownSession . EnableKernelProvider ( KernelTraceEventParser . Keywords . Process | KernelTraceEventParser . Keywords . ImageLoad ) ;
1167+ }
1168+ LogFile . WriteLine ( "InMemoryCircularBuffer Set, Finished Kernel Rundown" ) ;
11611169 }
1170+ kernelSession . Stop ( ) ;
11621171 }
1163- kernelSession . Stop ( ) ;
11641172 }
11651173 }
1166- }
1167- catch ( FileNotFoundException ) { LogFile . WriteLine ( "No Kernel events were active for this trace." ) ; }
1168- catch ( Exception e ) { if ( ! ( e is ThreadInterruptedException ) ) { LogFile . WriteLine ( "Error stopping Kernel session: " + e . Message ) ; } throw ; }
1174+ catch ( FileNotFoundException ) { LogFile . WriteLine ( "No Kernel events were active for this trace." ) ; }
1175+ catch ( Exception e ) { if ( ! ( e is ThreadInterruptedException ) ) { LogFile . WriteLine ( "Error stopping Kernel session: " + e . Message ) ; } throw ; }
1176+ } ) ;
11691177
11701178 string dataFile = null ;
1171- try
1179+ Task stopUser = Task . Factory . StartNew ( delegate ( )
11721180 {
1173- using ( TraceEventSession clrSession = new TraceEventSession ( s_UserModeSessionName , TraceEventSessionOptions . Attach ) )
1181+ try
11741182 {
1175- if ( parsedArgs . InMemoryCircularBuffer )
1183+ using ( TraceEventSession clrSession = new TraceEventSession ( s_UserModeSessionName , TraceEventSessionOptions . Attach ) )
11761184 {
1177- dataFile = parsedArgs . DataFile ;
1178- clrSession . SetFileName ( dataFile ) ; // Flush the file
1179- }
1180- else
1181- {
1182- dataFile = clrSession . FileName ;
1183- }
1185+ if ( parsedArgs . InMemoryCircularBuffer )
1186+ {
1187+ LogFile . WriteLine ( "InMemoryCircularBuffer Set, Dumping kernel log" ) ;
1188+ dataFile = parsedArgs . DataFile ;
1189+ clrSession . SetFileName ( dataFile ) ; // Flush the file
1190+ }
1191+ else
1192+ {
1193+ dataFile = clrSession . FileName ;
1194+ }
11841195
1185- clrSession . Stop ( ) ;
1196+ clrSession . Stop ( ) ;
11861197
1187- // Try to force the rundown of CLR method and loader events. This routine does not fail.
1188- DoClrRundownForSession ( dataFile , clrSession . SessionName , parsedArgs ) ;
1198+ // Try to force the rundown of CLR method and loader events. This routine does not fail.
1199+ DoClrRundownForSession ( dataFile , clrSession . SessionName , parsedArgs ) ;
1200+ }
11891201 }
1190- }
1191- catch ( Exception e ) { if ( ! ( e is ThreadInterruptedException ) ) { LogFile . WriteLine ( "Error stopping User session: " + e . Message ) ; } throw ; }
1202+ catch ( Exception e ) { if ( ! ( e is ThreadInterruptedException ) ) { LogFile . WriteLine ( "Error stopping User session: " + e . Message ) ; } throw ; }
1203+ } ) ;
11921204
1193- try
1205+ Task stopHeap = Task . Factory . StartNew ( delegate ( )
11941206 {
1195- using ( var heapSession = new TraceEventSession ( s_HeapSessionName , TraceEventSessionOptions . Attach ) )
1207+ try
11961208 {
1197- heapSession . Stop ( ) ;
1209+ using ( var heapSession = new TraceEventSession ( s_HeapSessionName , TraceEventSessionOptions . Attach ) )
1210+ {
1211+ heapSession . Stop ( ) ;
1212+ }
11981213 }
1199- }
1200- catch ( FileNotFoundException ) { LogFile . WriteLine ( "No Heap events were active for this trace." ) ; }
1201- catch ( Exception e ) { if ( ! ( e is ThreadInterruptedException ) ) { LogFile . WriteLine ( "Error stopping Heap session: " + e . Message ) ; } throw ; }
1214+ catch ( FileNotFoundException ) { LogFile . WriteLine ( "No Heap events were active for this trace." ) ; }
1215+ catch ( Exception e ) { if ( ! ( e is ThreadInterruptedException ) ) { LogFile . WriteLine ( "Error stopping Heap session: " + e . Message ) ; } throw ; }
1216+ } ) ;
1217+
1218+ // We stop the two sessions concurrently because we have notice that sometime the kernel session
1219+ // Takes a while to shutdown, and we want the user mode session to shutdown at basically the same time
1220+ // Doing them concurrently minimizes any skew.
1221+ Task . WaitAll ( stopKernel , stopUser , stopHeap ) ;
1222+ LogFile . WriteLine ( "Done stopping sessions." ) ;
12021223
12031224 UninstallETWClrProfiler ( LogFile ) ;
12041225
@@ -1268,10 +1289,10 @@ public void Abort(CommandLineArgs parsedArgs)
12681289
12691290 s_abortInProgress = true ;
12701291 m_logFile . WriteLine ( "Aborting tracing for sessions '" +
1271- KernelTraceEventParser . KernelSessionName + "' and '" + s_UserModeSessionName + "'." ) ;
1292+ s_KernelessionName + "' and '" + s_UserModeSessionName + "'." ) ;
12721293 try
12731294 {
1274- using ( var kernelSession = new TraceEventSession ( KernelTraceEventParser . KernelSessionName , TraceEventSessionOptions . Attach ) )
1295+ using ( var kernelSession = new TraceEventSession ( s_KernelessionName , TraceEventSessionOptions . Attach ) )
12751296 {
12761297 kernelSession . Stop ( true ) ;
12771298 }
@@ -3362,6 +3383,7 @@ private void WaitForRundownIdle(int minSeconds, int maxSeconds, string rundownFi
33623383 }
33633384
33643385 internal static string s_UserModeSessionName = "PerfViewSession" ;
3386+ internal static string s_KernelessionName = KernelTraceEventParser . KernelSessionName ;
33653387 private static string s_HeapSessionName { get { return s_UserModeSessionName + "Heap" ; } }
33663388
33673389 private static bool s_addedSupportDirToPath ;
@@ -3675,9 +3697,7 @@ private static void ParseProviderSpec(string providerSpec, TraceEventLevel level
36753697 providerGuid = TraceEventProviders . GetProviderGuidByName ( providerSpec ) ;
36763698 // Look it up by name
36773699 if ( providerGuid == Guid . Empty )
3678- {
3679- throw new ApplicationException ( "Could not find provider name '" + providerSpec + "'" ) ;
3680- }
3700+ TraceEventProviders . GetEventSourceGuidFromName ( providerSpec ) ;
36813701 }
36823702
36833703 retList . Add ( new ParsedProvider ( )
0 commit comments