Example #1
0
        private void StartTraceSession(DiagnoserActionParameters parameters)
        {
            var metricProviders = CompetitionCore.RunState[parameters.Config].Config
                                  .GetMetrics()
                                  .Select(m => m.ValuesProvider)
                                  .OfType <IEtwMetricValueProvider>()
                                  .Distinct()
                                  .ToArray();

            if (metricProviders.Length == 0)
            {
                _analysis = null;
                return;
            }

            var analysis = CreateAnalysis(parameters.Benchmark, parameters.Config, metricProviders);

            EtwHelpers.WorkaroundEnsureNativeDlls();

            bool allOk = false;

            try
            {
                BuildTraceSession(analysis);
                allOk = true;
            }
            finally
            {
                if (!allOk)
                {
                    CompleteTraceSession(analysis);
                    DisposeAnalysis(analysis);
                }
            }
        }
Example #2
0
        private void CompleteTraceSession(EtwDiagnoserAnalysis analysis)
        {
            var traceSession = analysis.TraceSession;

            if (traceSession != null)
            {
                traceSession.Flush();
                traceSession.Dispose();
            }
        }
Example #3
0
        private static DiagnoserTraceScopeEvent[] CollectDiagnoserEvents(EtwDiagnoserAnalysis analysis)
        {
            // ReSharper disable once ConvertToLocalFunction
            Func <TraceEvent, bool> currentRunFilter = e => (Guid)e.PayloadByName(DiagnoserEventSource.RunIdPayload) == analysis.RunGuid;

            var provider = new DiagnoserTimesProvider();

            using (var eventSource = new ETWTraceEventSource(analysis.TraceFile.Path))
                using (provider.Subscribe(eventSource, analysis.Benchmark, analysis.Config, currentRunFilter))
                {
                    eventSource.Process();
                }
            return(provider.GetEvents(analysis.Benchmark, analysis.Config).ToArray());
        }
Example #4
0
        private void DisposeAnalysis(EtwDiagnoserAnalysis analysis)
        {
            var config = analysis.Config;

            analysis.TraceSession?.Dispose();
            analysis.TraceFile.Dispose();

            var runState = _diagnoserState[config];

            Code.BugIf(runState.Analysis != analysis, "runState.Analysis != analysis");
            runState.Analysis = null;

            Code.BugIf(_analysis != analysis, "_analysis != analysis");
            _analysis = null;
        }
Example #5
0
        private static void ProcessCapturedEvents(EtwDiagnoserAnalysis analysis)
        {
            var events       = CollectDiagnoserEvents(analysis);
            var allProcesses = events.Select(e => e.ProcessId).ToHashSet();

            var timeRange = events.ToCompositeRange(
                e => e.Started ?? TimeSpan.MinValue,
                e => e.Stopped ?? TimeSpan.MaxValue);

            // ReSharper disable once ConvertToLocalFunction
            Func <TraceEvent, bool> timeAndProcessFilter = e =>
            {
                if (!allProcesses.Contains(e.ProcessID))
                {
                    return(false);
                }

                var t = TimeSpan.FromMilliseconds(e.TimeStampRelativeMSec);
                return(timeRange.Intersect(t, t).SubRanges.Any(r => r.Key.ProcessId == e.ProcessID));
            };

            using (var eventSource = new ETWTraceEventSource(analysis.TraceFile.Path))
            {
                if (eventSource.EventsLost > 0)
                {
                    analysis.WriteWarningMessage(
                        analysis.Benchmark.Target,
                        $"The analysis session contains {eventSource.EventsLost} lost event(s). Metric results may be inaccurate.",
                        "Consider to collect less events or to place the benchmark working directory on drive with least load.");
                }

                var allHandlers = new List <IDisposable>();
                foreach (var metricProvider in analysis.MetricProviders)
                {
                    // Already processed
                    if (metricProvider.ProviderGuid == DiagnoserEventSource.SourceGuid)
                    {
                        continue;
                    }

                    var handler = metricProvider.Subscribe(eventSource, analysis.Benchmark, analysis.Config, timeAndProcessFilter);
                    allHandlers.Add(handler);
                }

                eventSource.Process();
                allHandlers.DisposeAll();
            }
        }
Example #6
0
        private EtwDiagnoserAnalysis CreateAnalysis(Benchmark benchmark, IConfig config, IEtwMetricValueProvider[] metricProviders)
        {
            var diagnoserState = _diagnoserState[config];

            Code.BugIf(diagnoserState.Analysis != null, "runState.Analysis != null");
            Code.BugIf(_analysis != null, "_analysis != null");

            var analysis = new EtwDiagnoserAnalysis(benchmark, config, metricProviders);

            if (analysis.Config.KeepBenchmarkFiles)
            {
                analysis.TraceFile.SuppressDelete();
            }
            diagnoserState.Analysis = analysis;
            _analysis = analysis;
            return(analysis);
        }
Example #7
0
        private static void BuildTraceSession(EtwDiagnoserAnalysis analysis)
        {
            var traceSession = new TraceEventSession(analysis.RunGuid.ToString(), analysis.TraceFile.Path)
            {
                StopOnDispose = true
            };

            analysis.TraceSession = traceSession;

            var metricsByProvider = analysis.MetricProviders.ToLookup(p => p.ProviderGuid);

            // Kernel etw provider must be the first one.
            if (metricsByProvider.Contains(KernelTraceEventParser.ProviderGuid))
            {
                var metricValueProviders = metricsByProvider[KernelTraceEventParser.ProviderGuid];
                var flags = metricValueProviders
                            .Aggregate(0UL, (value, p) => value | p.ProviderKeywords);

                try
                {
                    traceSession.EnableKernelProvider((KernelTraceEventParser.Keywords)flags);
                }
                catch (UnauthorizedAccessException)
                {
                    var kernelMetrics = analysis.Config
                                        .GetMetrics()
                                        .Where(m => m.ValuesProvider is IEtwMetricValueProvider p && p.IsKernelMetric);

                    analysis.WriteSetupErrorMessage(
                        analysis.Benchmark.Target,
                        $"The config contains kernel metric(s) {kernelMetrics.Select(m => m.DisplayName).Join(", ")} and therefore requires elevated run.",
                        "Run the competition with elevated permissions (as administrator).");

                    throw;
                }
            }

            traceSession.EnableProvider(DiagnoserEventSource.SourceGuid);

            // Handle all other providers
            foreach (var metricsGroup in metricsByProvider)
            {
                // Already registered
                if (metricsGroup.Key == KernelTraceEventParser.ProviderGuid)
                {
                    continue;
                }
                if (metricsGroup.Key == DiagnoserEventSource.SourceGuid)
                {
                    continue;
                }

                var eventLevel = TraceEventLevel.Always;
                var keywords   = 0UL;
                foreach (var metricValueProvider in metricsGroup)
                {
                    if (eventLevel < metricValueProvider.EventLevel)
                    {
                        eventLevel = metricValueProvider.EventLevel;
                    }
                    keywords |= metricValueProvider.ProviderKeywords;
                }
                traceSession.EnableProvider(metricsGroup.Key, eventLevel, keywords);
            }
        }