/// <summary> /// Given a Linux event gotten from the trace, make its corresponding sample for the stack source. /// </summary> public StackSourceSample CreateSampleFor(LinuxEvent linuxEvent, BlockedTimeAnalyzer blockedTimeAnalyzer) { IEnumerable <Frame> frames = linuxEvent.CallerStacks; StackSourceCallStackIndex stackIndex = this.currentStackIndex; var sample = new StackSourceSample(this); sample.TimeRelativeMSec = linuxEvent.TimeMSec; sample.Metric = 1; stackIndex = this.InternFrames(frames.GetEnumerator(), stackIndex, linuxEvent.ProcessID, linuxEvent.ThreadID, blockedTimeAnalyzer); sample.StackIndex = stackIndex; return(sample); }
protected virtual void DoInterning() { BlockedTimeAnalyzer blockedTimeAnalyzer = doThreadTime ? new BlockedTimeAnalyzer() : null; foreach (var linuxEvent in this.parser.ParseSkippingPreamble(this.masterSource)) { blockedTimeAnalyzer?.UpdateThreadState(linuxEvent); this.AddSample(this.CreateSampleFor(linuxEvent, blockedTimeAnalyzer)); } blockedTimeAnalyzer?.FinishAnalyizing(); // TODO: Sort things in blocked time anaylizer // this.threadBlockedPeriods.Sort((x, y) => x.StartTime.CompareTo(y.StartTime)); this.TotalBlockedTime = blockedTimeAnalyzer != null ? blockedTimeAnalyzer.TotalBlockedTime : -1; }
private StackSourceCallStackIndex InternFrames(IEnumerator <Frame> frameIterator, StackSourceCallStackIndex stackIndex, int processID, int?threadid = null, BlockedTimeAnalyzer blockedTimeAnalyzer = null) { // We shouldn't advance the iterator if thread time is enabled because we need // to add an extra frame to the caller stack that is not in the frameIterator. // i.e. Short-circuiting prevents the frameIterator from doing MoveNext :) if (blockedTimeAnalyzer == null && !frameIterator.MoveNext()) { return(StackSourceCallStackIndex.Invalid); } StackSourceFrameIndex frameIndex; string frameDisplayName; if (blockedTimeAnalyzer != null) { // If doThreadTime is true, then we need to make sure that threadid is not null Contract.Requires(threadid != null, nameof(threadid)); if (blockedTimeAnalyzer.IsThreadBlocked((int)threadid)) { frameDisplayName = LinuxThreadState.BLOCKED_TIME.ToString(); } else { frameDisplayName = LinuxThreadState.CPU_TIME.ToString(); } } else { frameDisplayName = frameIterator.Current.DisplayName; } frameIndex = this.InternFrame(frameDisplayName); stackIndex = this.InternCallerStack(frameIndex, this.InternFrames(frameIterator, stackIndex, processID)); return(stackIndex); }
protected override void DoInterning() { int threadCount = MaxThreadCount; this.frames = new ConcurrentDictionary <string, StackSourceFrameIndex>(); this.parser.SkipPreamble(masterSource); Task[] tasks = new Task[threadCount]; List <BlockedTimeAnalyzer>[] threadBlockedTimeAnalyzers = null; if (this.doThreadTime) { threadBlockedTimeAnalyzers = new List <BlockedTimeAnalyzer> [tasks.Length]; } List <StackSourceSample>[] threadSamples = new List <StackSourceSample> [tasks.Length]; for (int i = 0; i < tasks.Length; i++) { threadSamples[i] = new List <StackSourceSample>(); if (threadBlockedTimeAnalyzers != null) { threadBlockedTimeAnalyzers[i] = new List <BlockedTimeAnalyzer>(); } var currentCulture = Thread.CurrentThread.CurrentCulture; var currentUICulture = Thread.CurrentThread.CurrentUICulture; tasks[i] = new Task((object givenArrayIndex) => { var oldCultures = Tuple.Create(Thread.CurrentThread.CurrentCulture, Thread.CurrentThread.CurrentUICulture); try { Thread.CurrentThread.CurrentCulture = currentCulture; Thread.CurrentThread.CurrentUICulture = currentUICulture; FastStream bufferPart; while ((bufferPart = this.GetNextSubStream(masterSource)) != null) { BlockedTimeAnalyzer blockedTimeAnalyzer = null; if (threadBlockedTimeAnalyzers != null) { blockedTimeAnalyzer = new BlockedTimeAnalyzer(); threadBlockedTimeAnalyzers[(int)givenArrayIndex].Add(blockedTimeAnalyzer); } foreach (LinuxEvent linuxEvent in this.parser.Parse(bufferPart)) { // If doThreadTime is true this is running on a single thread. blockedTimeAnalyzer?.UpdateThreadState(linuxEvent); StackSourceSample sample = this.CreateSampleFor(linuxEvent, blockedTimeAnalyzer); threadSamples[(int)givenArrayIndex].Add(sample); blockedTimeAnalyzer?.LinuxEventSampleAssociation(linuxEvent, sample); } bufferPart.Dispose(); } } finally { Thread.CurrentThread.CurrentCulture = oldCultures.Item1; Thread.CurrentThread.CurrentUICulture = oldCultures.Item2; } }, i); tasks[i].Start(); } Task.WaitAll(tasks); if (threadBlockedTimeAnalyzers != null) { List <BlockedTimeAnalyzer> allBlockedTimeAnalyzers = CustomExtensions.ConcatListsOfLists(threadBlockedTimeAnalyzers).ToList(); this.FixBlockedTimes(allBlockedTimeAnalyzers); foreach (var blockedTimeAnalyzer in allBlockedTimeAnalyzers) { this.TotalBlockedTime += blockedTimeAnalyzer.TotalBlockedTime; } } else { this.TotalBlockedTime = -1; } IEnumerable <StackSourceSample> allSamples = CustomExtensions.ConcatListsOfLists(threadSamples); this.AddSamples(allSamples); }