private void DoMetrics(LinuxEvent linuxEvent) { KeyValuePair <LinuxThreadState, LinuxEvent> sampleInfo; if (this.EndingStates.TryGetValue(linuxEvent.ThreadID, out sampleInfo)) { linuxEvent.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec; } // This is check for completed scheduler events, ones that start with prev_comm and have // corresponding next_comm. if (linuxEvent.Kind == EventKind.Scheduler) { SchedulerEvent schedEvent = (SchedulerEvent)linuxEvent; if (this.EndingStates.ContainsKey(schedEvent.Switch.PreviousThreadID) && this.EndingStates[schedEvent.Switch.PreviousThreadID].Key == LinuxThreadState.CPU_TIME) // Blocking { sampleInfo = this.EndingStates[schedEvent.Switch.PreviousThreadID]; this.EndingStates[schedEvent.Switch.PreviousThreadID] = new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.BLOCKED_TIME, linuxEvent); linuxEvent.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec; } if (this.EndingStates.TryGetValue(schedEvent.Switch.NextThreadID, out sampleInfo) && sampleInfo.Key == LinuxThreadState.BLOCKED_TIME) // Unblocking { this.EndingStates[schedEvent.Switch.NextThreadID] = new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.CPU_TIME, linuxEvent); // sampleInfo.Value.Period = linuxEvent.Time - sampleInfo.Value.Time; this.AddThreadPeriod(linuxEvent.ThreadID, sampleInfo.Value.TimeMSec, linuxEvent.TimeMSec); } } else if (linuxEvent.Kind == EventKind.Cpu) { int threadid; if (this.EndingCpuUsage.TryGetValue(linuxEvent.CpuNumber, out threadid) && threadid != linuxEvent.ThreadID) // Unblocking { if (this.EndingStates.TryGetValue(threadid, out sampleInfo)) { this.EndingStates[threadid] = new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.CPU_TIME, linuxEvent); sampleInfo.Value.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec; this.AddThreadPeriod(linuxEvent.ThreadID, sampleInfo.Value.TimeMSec, linuxEvent.TimeMSec); } } } this.EndingCpuUsage[linuxEvent.CpuNumber] = linuxEvent.ThreadID; }
private IEnumerable <LinuxEvent> NextEvent(Regex regex, FastStream source) { string line = string.Empty; while (true) { source.SkipWhiteSpace(); if (source.EndOfStream) { break; } EventKind eventKind = EventKind.Cpu; StringBuilder sb = new StringBuilder(); // Command - Stops at first number AFTER whitespace while (!this.IsNumberChar((char)source.Current)) { sb.Append(' '); source.ReadAsciiStringUpToTrue(sb, delegate(byte c) { return(!char.IsWhiteSpace((char)c)); }); source.SkipWhiteSpace(); } string comm = sb.ToString().Trim(); sb.Clear(); // Process ID int pid = source.ReadInt(); source.MoveNext(); // Move past the "/" // Thread ID int tid = source.ReadInt(); // CPU source.SkipWhiteSpace(); source.MoveNext(); // Move past the "[" int cpu = source.ReadInt(); source.MoveNext(); // Move past the "]" // Time source.SkipWhiteSpace(); source.ReadAsciiStringUpTo(':', sb); double time = double.Parse(sb.ToString()) * 1000; // To convert to MSec sb.Clear(); source.MoveNext(); // Move past ":" // Time Property source.SkipWhiteSpace(); int timeProp = -1; if (this.IsNumberChar((char)source.Current)) { timeProp = source.ReadInt(); } // Event Name source.SkipWhiteSpace(); source.ReadAsciiStringUpTo(':', sb); string eventName = sb.ToString(); sb.Clear(); source.MoveNext(); // Event Properties // I mark a position here because I need to check what type of event this is without screwing up the stream var markedPosition = source.MarkPosition(); source.ReadAsciiStringUpTo('\n', sb); string eventDetails = sb.ToString().Trim(); sb.Clear(); if (eventDetails.Length >= SchedulerEvent.Name.Length && eventDetails.Substring(0, SchedulerEvent.Name.Length) == SchedulerEvent.Name) { eventKind = EventKind.Scheduler; } // Now that we know the header of the trace, we can decide whether or not to skip it given our pattern if (regex != null && !regex.IsMatch(eventName)) { while (true) { source.MoveNext(); if (this.IsEndOfSample(source, source.Current, source.Peek(1))) { break; } } yield return(null); } else { LinuxEvent linuxEvent; Frame threadTimeFrame = null; // For the sake of immutability, I have to do a similar if-statement twice. I'm trying to figure out a better way // but for now this will do. ScheduleSwitch schedSwitch = null; if (eventKind == EventKind.Scheduler) { source.RestoreToMark(markedPosition); schedSwitch = this.ReadScheduleSwitch(source); source.SkipUpTo('\n'); } IEnumerable <Frame> frames = this.ReadFramesForSample(comm, pid, tid, threadTimeFrame, source); if (eventKind == EventKind.Scheduler) { linuxEvent = new SchedulerEvent(comm, tid, pid, time, timeProp, cpu, eventName, eventDetails, frames, schedSwitch); } else { linuxEvent = new CpuEvent(comm, tid, pid, time, timeProp, cpu, eventName, eventDetails, frames); } yield return(linuxEvent); } } }