public string ComputeContextSwitches() { ContextSwitchResult result = ComputeContextSwitchesRaw(); return(FormatContextSwitchResult(result)); }
public ContextSwitchResult ComputeContextSwitchesRaw() { IContextSwitchParameters icswitchparms = itparms.ContextSwitchParameters; bool fSimulateHyperthreading = icswitchparms.SimulateHyperthreading; bool fSortBySwitches = icswitchparms.SortBySwitches; bool fComputeReasons = icswitchparms.ComputeReasons; int nTop = icswitchparms.TopThreadCount; ByteWindow bT = new ByteWindow(); long timeTotal = 0; int switchesTotal = 0; tStart = itparms.T0; tEnd = itparms.T1; ThreadStat[] stats = NewThreadStats(); CPUState[] state = new CPUState[maxCPU]; int idCSwitch = atomsRecords.Lookup("CSwitch"); bool[] threadFilters = itparms.GetThreadFilters(); InitializeStartingCPUStates(state, idCSwitch); // rewind ETWLineReader l = StandardLineReader(); foreach (ByteWindow b in l.Lines()) { if (l.idType != idCSwitch) { continue; } int oldTid = b.GetInt(fldCSwitchOldTID); int cpu = b.GetInt(fldCSwitchCPU); timeTotal += AddCSwitchTime(fSimulateHyperthreading, l.t, stats, state); int newTid = b.GetInt(fldCSwitchNewTID); int idx = FindThreadInfoIndex(l.t, oldTid); stats[idx].switches++; switchesTotal++; if (fComputeReasons) { bT.Assign(b, fldCSwitchWaitReason).Trim(); int id = atomsReasons.EnsureContains(bT); if (stats[idx].swapReasons == null) { stats[idx].swapReasons = new int[maxReasons]; } stats[idx].swapReasons[id]++; } state[cpu].active = true; state[cpu].tid = newTid; state[cpu].time = l.t; } timeTotal += AddCSwitchTime(fSimulateHyperthreading, l.t1, stats, state); if (fSortBySwitches) { Array.Sort(stats, delegate(ThreadStat c1, ThreadStat c2) { if (c1.switches > c2.switches) { return(-1); } if (c1.switches < c2.switches) { return(1); } return(0); } ); } else { Array.Sort(stats, delegate(ThreadStat c1, ThreadStat c2) { if (c1.time > c2.time) { return(-1); } if (c1.time < c2.time) { return(1); } return(0); } ); } var result = new ContextSwitchResult(); result.stats = stats; result.switchesTotal = switchesTotal; result.timeTotal = timeTotal; result.fSortBySwitches = fSortBySwitches; result.reasonsComputed = fComputeReasons; result.threadFilters = threadFilters; result.countCPU = maxCPU; result.nTop = nTop; return(result); }
public string FormatContextSwitchResult(ContextSwitchResult results) { int nTop = results.nTop; string[] reasonNames = new string[atomsReasons.Count]; for (int i = 0; i < reasonNames.Length; i++) { reasonNames[i] = atomsReasons.MakeString(i); } ThreadStat[] stats = results.stats; int ithreadIdle = IdleThreadIndex; int iStatsIdle = 0; // find where the idle thread landed after sorting for (int i = 0; i < stats.Length; i++) { if (stats[i].ithread == ithreadIdle) { iStatsIdle = i; break; } } StringWriter sw = new StringWriter(); sw.WriteLine("Start time: {0:n0} End time: {1:n0} Interval Length: {2:n0}", tStart, tEnd, tEnd - tStart); sw.WriteLine(); sw.WriteLine("CPUs: {0:n0}, Total CPU Time: {1:n0} usec. Total Switches: {2:n0} Idle: {3,5:f1}% Busy: {4,5:f1}%", results.countCPU, results.timeTotal, results.switchesTotal, stats[iStatsIdle].time * 100.0 / results.timeTotal, (results.timeTotal - stats[iStatsIdle].time) * 100.0 / results.timeTotal); sw.WriteLine(); sw.WriteLine("{0,20} {1,17} {2,35} {3,5} {4,32} {5}", " Time (usec)", " Switches", "Process ( PID)", " TID", "Run Mask", "ThreadProc"); sw.WriteLine("{0,20} {1,17} {2,35} {3,5} {4,32} {5}", "-------------------", "---------------", "--------------", "----", "--------", "----------"); char[] maskChars = new char[32]; for (int i = 0; i < Math.Min(threads.Count, nTop); i++) { int ithread = stats[i].ithread; if (stats[i].time == 0) { continue; } if (!results.threadFilters[ithread]) { continue; } for (int bit = 0; bit < 32; bit++) { maskChars[bit] = ((stats[i].runmask & (1 << bit)) != 0 ? 'X' : '_'); } sw.WriteLine("{0,11:n0} ({1,5:f1}%) {2,8:n0} ({3,5:f1}%) {4,35} {5,5} {6} {7}", stats[i].time, stats[i].time * 100.0 / results.timeTotal, stats[i].switches, stats[i].switches * 100.0 / results.switchesTotal, ByteWindow.MakeString(threads[ithread].processPid), threads[ithread].threadid, new String(maskChars), ByteWindow.MakeString(threads[ithread].threadproc) ); if (results.reasonsComputed) { int[] swapReasons = stats[i].swapReasons; if (swapReasons != null) { for (int k = 0; k < swapReasons.Length; k++) { if (swapReasons[k] > 0) { sw.WriteLine(" {0,17} {1}", reasonNames[k], swapReasons[k]); } } } sw.WriteLine(); } } if (results.fSimulateHyperthreading) { sw.WriteLine(); sw.WriteLine("Hyperthreading Simulation was used to attribute idle cost more accurately"); } return(sw.ToString()); }