コード例 #1
0
        public static StackSource AnyStacks(this TraceLog eventLog, TraceProcess process = null, bool showUnknownAddresses = false, Predicate <TraceEvent> predicate = null)
        {
            var stackSource = new MutableTraceEventStackSource(eventLog);
            var sample      = new StackSourceSample(stackSource);

            TraceEvents events = process == null?eventLog.Events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID != 0) : process.EventsInProcess.Filter(x => predicate == null || predicate(x));

            var eventSource = events.GetSource();

            eventSource.AllEvents += data =>
            {
                var callStackIdx = data.CallStackIndex();
                StackSourceCallStackIndex stackIndex = callStackIdx != CallStackIndex.Invalid ? stackSource.GetCallStack(callStackIdx, data) : StackSourceCallStackIndex.Invalid;

                var eventNodeName = "Event " + data.ProviderName + "/" + data.EventName;
                stackIndex              = stackSource.Interner.CallStackIntern(stackSource.Interner.FrameIntern(eventNodeName), stackIndex);
                sample.StackIndex       = stackIndex;
                sample.TimeRelativeMSec = data.TimeStampRelativeMSec;
                sample.Metric           = 1;
                stackSource.AddSample(sample);
            };

            eventSource.Process();

            stackSource.DoneAddingSamples();

            return(stackSource);
        }
コード例 #2
0
        internal void StopScan(StreamscanrequestStartArgs_V1TraceData data)
        {
            // Get the requesting user process based on the PID logged inside the engine.
            TraceProcess process      = _traceLog.Processes.GetProcess(data.PID, data.TimeStampRelativeMSec);
            ProcessIndex processIndex = process.ProcessIndex;

            if (processIndex == ProcessIndex.Invalid)
            {
                return;
            }

            // Get the file scan operation.
            Dictionary <ThreadIndex, FileScanOperation> processContainer = GetOrCreateProcessContainer(processIndex);
            FileScanOperation operation = processContainer.Values.Where(s => s.File.Equals(data.Path, System.StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

            if (operation != null)
            {
                operation.StopTimeRelativeMSec = data.TimeStampRelativeMSec;

                // Create the stack.
                StackSourceFrameIndex fileNodeIndex   = _stackSource.Interner.FrameIntern($"File ({operation.File})");
                StackSourceFrameIndex reasonNodeIndex = _stackSource.Interner.FrameIntern($"Reason ({(operation.Reason != null ? operation.Reason : "Unknown")})");
                StackSourceFrameIndex resultNodeIndex = _stackSource.Interner.FrameIntern($"Scan Result ({operation.Result})");
                _sample.StackIndex       = _stackSource.Interner.CallStackIntern(resultNodeIndex, operation.RequestorStack);
                _sample.StackIndex       = _stackSource.Interner.CallStackIntern(reasonNodeIndex, _sample.StackIndex);
                _sample.StackIndex       = _stackSource.Interner.CallStackIntern(fileNodeIndex, _sample.StackIndex);
                _sample.Metric           = (float)(operation.StopTimeRelativeMSec - operation.StartTimeRelativeMSec);
                _sample.TimeRelativeMSec = operation.StartTimeRelativeMSec;
                _stackSource.AddSample(_sample);
            }
        }
コード例 #3
0
 public static bool ManagedProcess(this TraceProcess process)
 {
     return(process.LoadedModules.Where(module =>
                                        module.Name.Equals("clr", StringComparison.OrdinalIgnoreCase) ||
                                        module.Name.Equals("coreclr", StringComparison.OrdinalIgnoreCase) ||
                                        module.Name.Equals("mscorwks", StringComparison.OrdinalIgnoreCase)).Count() > 0);
 }
コード例 #4
0
        /// <summary>
        /// Constructs a new processor for the provided data files.
        /// </summary>
        /// <param name="preprocessor">The preprocessor to use (copies everything)</param>
        public EventProcessor(EventProcessor preprocessor)
        {
            // Copy stuff we already calculated
            this.TraceLog         = preprocessor.TraceLog;
            this.Counters         = preprocessor.Counters;
            this.Start            = preprocessor.Start;
            this.End              = preprocessor.End;
            this.Duration         = preprocessor.Duration;
            this.Interval         = preprocessor.Interval;
            this.Count            = preprocessor.Count;
            this.CoreCount        = preprocessor.CoreCount;
            this.Process          = preprocessor.Process;
            this.Threads          = preprocessor.Threads;
            this.Frames           = preprocessor.Frames;
            this.Faults           = preprocessor.Faults;
            this.Switches         = preprocessor.Switches;
            this.Lifetimes        = preprocessor.Lifetimes;
            this.LockAcquisitions = preprocessor.LockAcquisitions;

            // A last switch per core
            for (int i = 0; i < this.CoreCount; ++i)
            {
                this.LookupLastSwitch.Add(i, null);
            }
        }
コード例 #5
0
        private GCHeapSimulator CreateNewSimulator(TraceProcess process)
        {
            var ret = new GCHeapSimulator(m_source, process, m_stackSource, m_log, UseOnlyAllocTicks);

            OnNewGCHeapSimulator?.Invoke(ret);
            return(ret);
        }
コード例 #6
0
 public PgoTraceProcess(TraceProcess traceProcess)
 {
     TraceProcess = traceProcess;
     foreach (var assemblyLoadTrace in traceProcess.EventsInProcess.ByEventType <AssemblyLoadUnloadTraceData>())
     {
         _assemblyToCLRInstanceIDMap[assemblyLoadTrace.AssemblyID] = assemblyLoadTrace.ClrInstanceID;
     }
 }
コード例 #7
0
 public DiagnosticProcessInfo(TraceProcess p, bool isCoreProcess = false)
 {
     Name          = p.Name;
     Id            = p.ProcessID;
     CPUMSec       = p.CPUMSec;
     SiteName      = GetSiteName(p);
     IsCoreProcess = isCoreProcess;
 }
コード例 #8
0
ファイル: JitStats.cs プロジェクト: zhaoyingju/perfview
        public static void ToXml(TextWriter writer, TraceProcess stats, TraceLoadedDotNetRuntime runtime, string indent)
        {
            JITStatsEx statsEx = JITStatsEx.Create(runtime);

            // TODO pay attention to indent;
            writer.Write(" <JitProcess Process=\"{0}\" ProcessID=\"{1}\" JitTimeMSec=\"{2:n3}\" Count=\"{3}\" ILSize=\"{4}\" NativeSize=\"{5}\"",
                         stats.Name, stats.ProcessID, runtime.JIT.Stats().TotalCpuTimeMSec, runtime.JIT.Stats().Count, runtime.JIT.Stats().TotalILSize, runtime.JIT.Stats().TotalNativeSize);
            if (stats.CPUMSec != 0)
            {
                writer.Write(" ProcessCpuTimeMsec=\"{0}\"", stats.CPUMSec);
            }
            if (!string.IsNullOrEmpty(stats.CommandLine))
            {
                writer.Write(" CommandLine=\"{0}\"", XmlUtilities.XmlEscape(stats.CommandLine, false));
            }
            writer.WriteLine(">");
            writer.WriteLine("  <JitEvents>");
            foreach (TraceJittedMethod _event in runtime.JIT.Methods)
            {
                ToXml(writer, _event);
            }
            writer.WriteLine("  </JitEvents>");

            writer.WriteLine(" <ModuleStats Count=\"{0}\" TotalCount=\"{1}\" TotalJitTimeMSec=\"{2:n3}\" TotalILSize=\"{3}\" TotalNativeSize=\"{4}\">",
                             statsEx.TotalModuleStats.Count, runtime.JIT.Stats().Count, runtime.JIT.Stats().TotalCpuTimeMSec, runtime.JIT.Stats().TotalILSize, runtime.JIT.Stats().TotalNativeSize);

            // Sort the module list by Jit Time;
            List <string> moduleNames = new List <string>(statsEx.TotalModuleStats.Keys);

            moduleNames.Sort(delegate(string x, string y)
            {
                double diff = statsEx.TotalModuleStats[y].TotalCpuTimeMSec - statsEx.TotalModuleStats[x].TotalCpuTimeMSec;
                if (diff > 0)
                {
                    return(1);
                }
                else if (diff < 0)
                {
                    return(-1);
                }
                return(0);
            });

            foreach (string moduleName in moduleNames)
            {
                JITStats info = statsEx.TotalModuleStats[moduleName];
                writer.Write("<Module");
                writer.Write(" JitTimeMSec={0}", StringUtilities.QuotePadLeft(info.TotalCpuTimeMSec.ToString("n3"), 11));
                writer.Write(" Count={0}", StringUtilities.QuotePadLeft(info.Count.ToString(), 7));
                writer.Write(" ILSize={0}", StringUtilities.QuotePadLeft(info.TotalILSize.ToString(), 9));
                writer.Write(" NativeSize={0}", StringUtilities.QuotePadLeft(info.TotalNativeSize.ToString(), 9));
                writer.Write(" Name=\"{0}\"", moduleName);
                writer.WriteLine("/>");
            }
            writer.WriteLine("  </ModuleStats>");

            writer.WriteLine(" </JitProcess>");
        }
コード例 #9
0
        // Advanced usage
        public StackSourceCallStackIndex GetCallStackForProcess(TraceProcess process)
        {
            string ptrSize              = process.Is64Bit ? "64" : "32";
            var    processName          = "Process" + ptrSize + " " + process.Name + " (" + process.ProcessID + ")";
            var    internedProcessFrame = Interner.FrameIntern(processName, m_emptyModuleIdx);
            var    processStack         = Interner.CallStackIntern(internedProcessFrame, StackSourceCallStackIndex.Invalid);

            return(processStack);
        }
コード例 #10
0
        public PinningStackAnalysis(TraceEventDispatcher source, TraceProcess process, MutableTraceEventStackSource stackSource, TextWriter log)
            : base(source, process, stackSource, log)
        {
            var clrPrivateParser = new ClrPrivateTraceEventParser(source);

            clrPrivateParser.GCSetGCHandle += OnSetGCHandle;
            source.Clr.GCSetGCHandle       += OnSetGCHandle;

            AllocateObject = () => new PinningStackAnalysisObject();
        }
コード例 #11
0
        GCHeapSimulator CreateNewSimulator(TraceProcess process)
        {
            var ret = new GCHeapSimulator(m_source, process, m_stackSource, m_log, UseOnlyAllocTicks);

            if (OnNewGCHeapSimulator != null)
            {
                OnNewGCHeapSimulator(ret);
            }
            return(ret);
        }
コード例 #12
0
ファイル: IProcess.cs プロジェクト: lelonek1/perfview-1
        /// <summary>
        /// Find the depth of a process (0 means I have no parent).
        /// </summary>
        private static int ParentDepth(TraceProcess process)
        {
            int ret = 0;

            while (process.Parent != null && process.ProcessID != 0)
            {
                process = process.Parent;
                ret++;
            }
            return(ret);
        }
コード例 #13
0
 public void WriteIssuesForProcess(TraceProcess process, List <AutomatedAnalysisIssue> issues)
 {
     _writer.WriteLine($"<H3>Process {process.ProcessID}: {process.CommandLine}</H3>");
     _writer.WriteLine("<Table Border=\"1\">");
     _writer.WriteLine("<TR><TH>Issue Title</TH><TH>Notes</TH></TR>");
     foreach (AutomatedAnalysisIssue issue in issues)
     {
         _writer.WriteLine($"<TR><TD>{issue.Title}</TD><TD>{issue.Description}<BR/><BR/>More details: <A HREF=\"{issue.URL}\">{issue.URL}</A></TD></TR>");
     }
     _writer.WriteLine("</Table>");
 }
コード例 #14
0
        public static StackSource CPUStacks(this TraceLog eventLog, TraceProcess process = null, bool showUnknownAddresses = false, Predicate <TraceEvent> predicate = null)
        {
            TraceEvents events = process == null?eventLog.Events.Filter(x => (predicate == null || predicate(x)) && x is SampledProfileTraceData && x.ProcessID != 0) : process.EventsInProcess.Filter(x => (predicate == null || predicate(x)) && x is SampledProfileTraceData);

            var traceStackSource = new TraceEventStackSource(events)
            {
                ShowUnknownAddresses = showUnknownAddresses
            };

            return(traceStackSource);
        }
コード例 #15
0
 public GCHeapSimulator this[TraceProcess process]
 {
     get
     {
         var ret = m_simulators[(int)process.ProcessIndex];
         if (ret == null)
         {
             m_simulators[(int)process.ProcessIndex] = ret = CreateNewSimulator(process);
         }
         return(ret);
     }
 }
コード例 #16
0
        private StackView GetCPUStacks(Process process)
        {
            StackView    stackView    = null;
            TraceProcess traceProcess = UnderlyingSource.Processes[(ProcessIndex)process.UniqueID];

            if (traceProcess != null)
            {
                StackSource stackSource = UnderlyingSource.CPUStacks(traceProcess);
                stackView = new StackView(traceProcess.Log, stackSource, SymbolReader);
            }
            return(stackView);
        }
コード例 #17
0
        StackView ITrace.GetCPUStacks(AnalyzerTraceProcess process)
        {
            StackView    stackView    = null;
            TraceProcess traceProcess = TraceLog.Processes[(ProcessIndex)process.UniqueID];

            if (traceProcess != null)
            {
                StackSource stackSource = TraceLog.CPUStacks(traceProcess);
                stackView = new StackView(traceProcess.Log, stackSource, SymbolReader);
            }
            return(stackView);
        }
コード例 #18
0
        public static StackSource Exceptions(this TraceEvents events, TraceProcess process = null, Predicate <TraceEvent> predicate = null)
        {
            // optimization only
            if (process != null)
            {
                var start = Math.Max(events.StartTimeRelativeMSec, process.StartTimeRelativeMsec);
                var end   = Math.Min(events.EndTimeRelativeMSec, process.EndTimeRelativeMsec);
                events = events.FilterByTime(start, end);
                events = events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID == process.ProcessID);
            }
            else
            {
                events = events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID != 0); // TODO: Is it really correc that x.ProcessID != 0 should be there? What if we want see these?
            }

            var eventSource = events.GetSource();
            var stackSource = new MutableTraceEventStackSource(events.Log)
            {
                ShowUnknownAddresses = true
            };
            var sample = new StackSourceSample(stackSource);

            eventSource.Clr.ExceptionStart += data =>
            {
                sample.Metric           = 1;
                sample.TimeRelativeMSec = data.TimeStampRelativeMSec;

                // Create a call stack that ends with the 'throw'
                var nodeName  = "Throw(" + data.ExceptionType + ") " + data.ExceptionMessage;
                var nodeIndex = stackSource.Interner.FrameIntern(nodeName);
                sample.StackIndex = stackSource.Interner.CallStackIntern(nodeIndex, stackSource.GetCallStack(data.CallStackIndex(), data));
                stackSource.AddSample(sample);
            };

            eventSource.Kernel.MemoryAccessViolation += data =>
            {
                sample.Metric           = 1;
                sample.TimeRelativeMSec = data.TimeStampRelativeMSec;

                // Create a call stack that ends with the 'throw'
                var nodeName  = "AccessViolation(ADDR=" + data.VirtualAddress.ToString("x") + ")";
                var nodeIndex = stackSource.Interner.FrameIntern(nodeName);
                sample.StackIndex = stackSource.Interner.CallStackIntern(nodeIndex, stackSource.GetCallStack(data.CallStackIndex(), data));
                stackSource.AddSample(sample);
            };

            eventSource.Process();

            stackSource.DoneAddingSamples();

            return(stackSource);
        }
コード例 #19
0
 private void RuntimeGCEnd(TraceProcess traceProcess, Microsoft.Diagnostics.Tracing.Analysis.GC.TraceGC gc)
 {
     if (traceProcess.ProcessID == _currentProcessId)
     {
         if (!_isMetricAlreadyCaptured)
         {
             lock (_lock)
                 _isMetricAlreadyCaptured = true;
         }
         _gcTimeInTicks = (long)gc.DurationMSec * 10_000;
         _gcCount       = (uint)gc.Number;
     }
 }
コード例 #20
0
        public List <AutomatedAnalysisIssue> this[TraceProcess process]
        {
            get
            {
                List <AutomatedAnalysisIssue> issues;
                if (!_issues.TryGetValue(process, out issues))
                {
                    issues = new List <AutomatedAnalysisIssue>();
                    _issues.Add(process, issues);
                }

                return(issues);
            }
        }
コード例 #21
0
        // Keep this for now because GLAD depends on it.
        public List <AnalyzerIssue> this[TraceProcess process]
        {
            get
            {
                AnalyzerTraceProcess traceProcess = new AnalyzerTraceProcess((int)process.ProcessIndex, process.ProcessID, process.CommandLine, process.ManagedProcess());
                List <AnalyzerIssue> issues;
                if (!_issues.TryGetValue(traceProcess, out issues))
                {
                    issues = new List <AnalyzerIssue>();
                    _issues.Add(traceProcess, issues);
                }

                return(issues);
            }
        }
コード例 #22
0
ファイル: IProcess.cs プロジェクト: lelonek1/perfview-1
        private static int Compare(TraceProcess process1, int depth1, TraceProcess process2, int depth2)
        {
            if (process1 == process2)
            {
                return(0);
            }
            int ret;

            if (depth1 > depth2)
            {
                ret = Compare(process1.Parent, depth1 - 1, process2, depth2);
                if (ret == 0)
                {
                    ret = 1;
                }
                return(ret);
            }
            if (depth2 > depth1)
            {
                ret = Compare(process1, depth1, process2.Parent, depth2 - 1);
                if (ret == 0)
                {
                    ret = -1;
                }
                return(ret);
            }
            if (depth1 > 0)
            {
                ret = Compare(process1.Parent, depth1 - 1, process2.Parent, depth2 - 1);
                if (ret != 0)
                {
                    return(ret);
                }
            }

            // If parents are the same, we sort by time. youngest first
            ret = -process1.StartTime100ns.CompareTo(process2.StartTime100ns);
            if (ret != 0)
            {
                return(ret);
            }

            // If times are the same, sort by process ID (decending)
            return(-process1.ProcessID.CompareTo(process2.ProcessID));
        }
コード例 #23
0
 private void ProcessEventsFromAutoLoggerFirst()
 {
     if (myUnprocessedEvents != null && myUnprocessedEvents.Count > 0)
     {
         // since the AutogLogger session has no kernel session attached we only get raw process ids
         // To work around that we fill in the process names from still running processes from the realtime session
         foreach (WMIStart wmiStartEvent in myUnprocessedEvents)
         {
             TraceProcess process = mySource?.TraceLog.Processes.Where(p => p.ProcessID == wmiStartEvent.ClientProcessId).FirstOrDefault();
             if (process != null)
             {
                 wmiStartEvent.ClientProcess = process.CommandLine;
             }
             OnWMIOperationStart?.Invoke(wmiStartEvent);
         }
         myUnprocessedEvents.Clear();
     }
 }
コード例 #24
0
        public static StackSource CPUStacks(this TraceLog eventLog, TraceProcess process = null, Predicate <TraceEvent> predicate = null)
        {
            TraceEvents events;

            if (process == null)
            {
                events = eventLog.Events.Filter((x) => ((predicate == null) || predicate(x)) && x is SampledProfileTraceData && x.ProcessID != 0);
            }
            else
            {
                events = process.EventsInProcess.Filter((x) => ((predicate == null) || predicate(x)) && x is SampledProfileTraceData);
            }

            var traceStackSource = new TraceEventStackSource(events);

            // We clone the samples so that we don't have to go back to the ETL file from here on.
            return(CopyStackSource.Clone(traceStackSource));
        }
コード例 #25
0
        public static void ToHtml(TextWriter writer, TraceProcess stats, Etlx.TraceLog traceLog)
        {
            Etlx.TraceProcess traceProcess = traceLog.Processes.GetProcess(stats.ProcessID, stats.StartTimeRelativeMsec + 1);
            if (traceProcess == null)
            {
                return;
            }

            writer.WriteLine("<H3><A Name=\"Stats_{0}\"><font color=\"blue\">File Version Information for for Process {1,5}: {2}</font><A></H3>", stats.ProcessID, stats.ProcessID, stats.Name);
            writer.WriteLine("<UL>");
            {
                writer.WriteLine("<LI>CommandLine: {0}</LI>", traceProcess.CommandLine);
            }
            writer.WriteLine("</UL>");

            writer.WriteLine("<H4><A Name=\"Events_{0}\">Individual Loaded Modules for Process {1,5}: {2}<A></H4>", stats.ProcessID, stats.ProcessID, stats.Name);

            writer.WriteLine("<Center>");
            writer.WriteLine("<Table Border=\"1\">");
            writer.Write(
                "<TR>" +
                "<TH>File Path</TH>" +
                "<TH>Version</TH>" +
                "</TR>");
            List <Etlx.TraceLoadedModule> modules = traceProcess.LoadedModules.ToList();

            modules.Sort((Etlx.TraceLoadedModule t1, Etlx.TraceLoadedModule t2) => { return(string.Compare(t1.Name, t2.Name)); });
            foreach (Etlx.TraceLoadedModule module in modules)
            {
                Etlx.TraceModuleFile moduleFile = module.ModuleFile;
                writer.Write(
                    "<TR>" +
                    "<TD Align=\"Left\">{0}</TD>" +
                    "<TD Align=\"Center\">{1}</TD>" +
                    "</TR>",
                    moduleFile.FilePath,
                    moduleFile.FileVersion);
            }
            writer.WriteLine("</Table>");
            writer.WriteLine("</Center>");

            writer.WriteLine("<HR/><HR/><BR/><BR/>");
        }
コード例 #26
0
        private TraceProcess CheckIfParentIsW3wp(TraceProcess p)
        {
            int          counter = 0;
            TraceProcess parent  = null;

            while (p != null && p.ProcessID != 0 && counter < MAX_PARENT_PROCESS_LEVELS_TO_CHECK)
            {
                counter++;
                if (p.Name == "w3wp")
                {
                    parent = p;
                    break;
                }
                if (p.ParentID == 0)
                {
                    break;
                }
            }
            return(parent);
        }
コード例 #27
0
        internal void StartScan(StreamscanrequestStartArgs_V1TraceData data)
        {
            // Get the requesting user process based on the PID logged inside the engine.
            TraceProcess process      = _traceLog.Processes.GetProcess(data.PID, data.TimeStampRelativeMSec);
            ProcessIndex processIndex = process.ProcessIndex;

            if (processIndex == ProcessIndex.Invalid)
            {
                return;
            }

            // Get the file scan operation.
            Dictionary <ThreadIndex, FileScanOperation> processContainer = GetOrCreateProcessContainer(processIndex);
            FileScanOperation operation = processContainer.Values.Where(s => s.File.Equals(data.Path, System.StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

            if (operation != null)
            {
                operation.StartTimeRelativeMSec = data.TimeStampRelativeMSec;
                _engineThreadToScanMap[(int)data.Thread().ThreadIndex] = operation;
            }
        }
コード例 #28
0
ファイル: EtlDiffer.cs プロジェクト: wzchua/roslyn-analyzers
        public static StackSource CreateStackSourceFromTraceProcess(TraceProcess process)
        {
            var events = process.EventsInProcess;
            var start  = Math.Max(events.StartTimeRelativeMSec, process.StartTimeRelativeMsec);
            var end    = Math.Min(events.EndTimeRelativeMSec, process.EndTimeRelativeMsec);

            events = events.FilterByTime(start, end);
            events = events.Filter(x => x is SampledProfileTraceData && x.ProcessID == process.ProcessID);

            using var symbolReader     = new SymbolReader(new StringWriter(), @"SRV*https://msdl.microsoft.com/download/symbols");
            symbolReader.SecurityCheck = path => true;

            var traceLog = process.Log;

            foreach (var module in process.LoadedModules)
            {
                traceLog.CodeAddresses.LookupSymbolsForModule(symbolReader, module.ModuleFile);
            }

            return(new TraceEventStackSource(events));
        }
コード例 #29
0
        public static StackSource AnyStacks(this TraceEvents events, TraceProcess process = null, Predicate <TraceEvent> predicate = null)
        {
            // optimization only
            if (process != null)
            {
                var start = Math.Max(events.StartTimeRelativeMSec, process.StartTimeRelativeMsec);
                var end   = Math.Min(events.EndTimeRelativeMSec, process.EndTimeRelativeMsec);
                events = events.FilterByTime(start, end);
                events = events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID == process.ProcessID);
            }
            else
            {
                events = events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID != 0); // TODO: Is it really correc that x.ProcessID != 0 should be there? What if we want see these?
            }

            var stackSource = new MutableTraceEventStackSource(events.Log)
            {
                ShowUnknownAddresses = true
            };
            var sample      = new StackSourceSample(stackSource);
            var eventSource = events.GetSource();

            eventSource.AllEvents += data =>
            {
                var callStackIdx = data.CallStackIndex();
                StackSourceCallStackIndex stackIndex = callStackIdx != CallStackIndex.Invalid ? stackSource.GetCallStack(callStackIdx, data) : StackSourceCallStackIndex.Invalid;

                var eventNodeName = "Event " + data.ProviderName + "/" + data.EventName;
                stackIndex              = stackSource.Interner.CallStackIntern(stackSource.Interner.FrameIntern(eventNodeName), stackIndex);
                sample.StackIndex       = stackIndex;
                sample.TimeRelativeMSec = data.TimeStampRelativeMSec;
                sample.Metric           = 1;
                stackSource.AddSample(sample);
            };

            eventSource.Process();
            stackSource.DoneAddingSamples();

            return(stackSource);
        }
コード例 #30
0
        public static StackSource SingleEventTypeStack(this TraceEvents events, TraceProcess process = null, Predicate <TraceEvent> predicate = null)
        {
            // optimization only
            if (process != null)
            {
                var start = Math.Max(events.StartTimeRelativeMSec, process.StartTimeRelativeMsec);
                var end   = Math.Min(events.EndTimeRelativeMSec, process.EndTimeRelativeMsec);
                events = events.FilterByTime(start, end);
                events = events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID == process.ProcessID);
            }
            else
            {
                events = events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID != 0); // TODO: Is it really correc that x.ProcessID != 0 should be there? What if we want see these?
            }

            var traceStackSource = new TraceEventStackSource(events)
            {
                ShowUnknownAddresses = true
            };

            return(CopyStackSource.Clone(traceStackSource));
        }
コード例 #31
0
        /// <summary>
        /// Constructs a new processor for the provided data files.
        /// </summary>
        /// <param name="preprocessor">The preprocessor to use (copies everything)</param>
        public EventProcessor(EventProcessor preprocessor)
        {
            // Copy stuff we already calculated
            this.TraceLog = preprocessor.TraceLog;
            this.Counters = preprocessor.Counters;
            this.Start = preprocessor.Start;
            this.End = preprocessor.End;
            this.Duration = preprocessor.Duration;
            this.Interval = preprocessor.Interval;
            this.Count = preprocessor.Count;
            this.CoreCount = preprocessor.CoreCount;
            this.Process = preprocessor.Process;
            this.Threads = preprocessor.Threads;
            this.Frames = preprocessor.Frames;
            this.Faults = preprocessor.Faults;
            this.Switches = preprocessor.Switches;
            this.Lifetimes = preprocessor.Lifetimes;
            this.LockAcquisitions = preprocessor.LockAcquisitions;

            // A last switch per core
            for (int i = 0; i < this.CoreCount; ++i)
                this.LookupLastSwitch.Add(i, null);
        }
コード例 #32
0
        /// <summary>
        /// Gets the sampling frames. This is used to analyze what the threads were doing 
        /// and splits the data into workable fixed intervals.
        /// </summary>
        /// <param name="processName">The process to analyze.</param>
        /// <param name="interval">The interval (in milliseconds) of a frame.</param>
        /// <returns></returns>
        private EventFrame[] GetFrames(string processName, ushort interval)
        {
            // Get the pid only
            var pid = this.TraceLog.Processes
                .Where(p => p.Name.StartsWith(processName))
                .FirstOrDefault()
                .ProcessID;

            // Mark of the start inside the process
            var benchmarkBegin = DateTime.MinValue;
            {
                var evt = TraceLog.Events
                    .Where(e => e.ProcessID == pid)
                    .Where(e => e.EventName.Contains("BenchmarkBegin"))
                    .FirstOrDefault();
                if(evt != null)
                    benchmarkBegin = evt.TimeStamp;
            }

            // Mark of the end inside the process
            var benchmarkEnd = DateTime.MinValue;
            {
                var evt = TraceLog.Events
                    .Where(e => e.ProcessID == pid)
                    .Where(e => e.EventName.Contains("BenchmarkEnd"))
                    .FirstOrDefault();
                if (evt != null)
                    benchmarkEnd = evt.TimeStamp;
            }

            // Look the process info
            this.Process = this.TraceLog.Processes
                .Where(p => p.Name.StartsWith(processName))
                .FirstOrDefault();

            // Get the threads
            this.Threads = this.Process.Threads
                .ToArray();

            // Define the timeframe of the experiment
            this.Start = benchmarkBegin == DateTime.MinValue
                ? new DateTime(Math.Max(this.Process.StartTime.Ticks, this.Counters.First().Time.Ticks))
                : benchmarkBegin;
            this.End = benchmarkEnd == DateTime.MinValue
                ? new DateTime(Math.Min(this.Process.EndTime.Ticks, this.Counters.Last().Time.Ticks))
                : benchmarkEnd;

            this.Duration = this.End - this.Start;
            this.Interval = TimeSpan.FromMilliseconds(interval);
            this.Count = (int)Math.Ceiling(this.Duration.TotalMilliseconds / this.Interval.TotalMilliseconds);

            Console.WriteLine("Analysis: Analyzing {0} process with {1} threads.", this.Process.Name, this.Threads.Length);
            Console.WriteLine("Analysis: duration = {0}", this.Duration);
            Console.WriteLine("Analysis: #cores = {0}", CoreCount);
            Console.WriteLine("Analysis: Creating #{0} frames for {1}ms. interval...", this.Count, this.Interval.TotalMilliseconds);

            // Get all context switches
            var safeWindow = TimeSpan.FromSeconds(1);
            this.Switches = this.TraceLog.Events
                .Where(e => e.EventName.StartsWith("Thread/CSwitch"))
                .Where(e => e.TimeStamp > this.Start - safeWindow)
                .Where(e => e.TimeStamp < this.End + safeWindow)
                .Select(sw => new ContextSwitch(sw))
                .OrderBy(sw => sw.TimeStamp100ns)
                .ToArray();

            // Get all lifetimes
            this.Lifetimes = this.TraceLog.Events
                .Where(e => e.EventName.StartsWith("Thread/Start") || e.EventName.StartsWith("Thread/End"))
                .Where(e => e.TimeStamp > this.Start - safeWindow)
                .Where(e => e.TimeStamp < this.End + safeWindow)
                .Select(e => new ThreadLifetime(e, e.EventName.StartsWith("Thread/Start") ? ThreadLifetimeType.Start : ThreadLifetimeType.End))
                .OrderBy(sw => sw.TimeStamp100ns)
                .ToArray();

            // Gets all page faults
            this.Faults = this.TraceLog.Events
                .Where(e => e.EventName.StartsWith("PageFault"))
                .Select(e => new PageFault(e))
                .ToArray();

            // Gets all lock acquisition events
            this.LockAcquisitions = this.TraceLog.Events
                .Where(e => e.EventName.EndsWith("LockSuccess") || e.EventName.EndsWith("LockFailure"))
                .Where(e => e.TimeStamp > this.Start - safeWindow)
                .Where(e => e.TimeStamp < this.End + safeWindow)
                .Select(e => new LockAcquisition(e, e.EventName.EndsWith("LockSuccess") ? LockAcquisitionType.Success : LockAcquisitionType.Failure))
                .OrderBy(sw => sw.TimeStamp100ns)
                .ToArray();

            // The list for our results
            var result = new List<EventFrame>();

            // Build a by-thread lookup cache
            for (int i = 0; i < this.Switches.Length;++i)
            {
                var sw = this.Switches[i];
                if (!this.LookupSwitchByThread.ContainsKey(sw.OldThreadId))
                    this.LookupSwitchByThread[sw.OldThreadId] = new List<ContextSwitch>();
                this.LookupSwitchByThread[sw.OldThreadId].Add(sw);
            }

            // Upsample at the specified interval
            var elapsed = 0d;
            for (int i = 0; i < this.Count; ++i)
            {
                // Current time
                var t = (int)this.Interval.TotalMilliseconds * i;

                // The interval starting time
                var timeFrom = this.Start + TimeSpan.FromMilliseconds(t);
                var timeTo = this.Start + TimeSpan.FromMilliseconds(t) + this.Interval;

                // For each core
                for (int core = 0; core < this.CoreCount; ++core)
                {
                    // Print out status
                    var begin = DateTime.Now;
                    var fid = (i * this.CoreCount + core + 1);
                    var fmx = (this.Count * this.CoreCount);
                    var eta = (elapsed / fid ) * (fmx - fid);
                    Console.WriteLine("[{0}] Progress: {1}/{2} ETA: {3}",
                        this.Process.Name,
                        fid, fmx,
                        TimeSpan.FromMilliseconds(eta).ToString());

                    // Get corresponding context switches that happened on that particular core in the specified time frame
                    var cs = this.Switches
                        .Where(e => e.TimeStamp >= timeFrom && e.TimeStamp <= timeTo)
                        .Where(e => e.ProcessorNumber == core)
                        .OrderBy(e => e.TimeStamp100ns);
                    // Console.WriteLine("Analysis: t = {0}, core = {1}, #hw = {2}, #cs = {3}", t, core, hw.Count(), cs.Count());

                    // Get an individual frame
                    var frame = GetFrame(timeFrom, core, cs);
                    //Console.WriteLine(frame.ToTable());
                    result.Add(frame);

                    // Calculate time spent analysing this frame
                    elapsed += (DateTime.Now - begin).TotalMilliseconds;
                }
            }

            // Return the resulting frames
            return result.ToArray();
        }