예제 #1
0
        public string ComputeContextSwitches()
        {
            ContextSwitchResult result = ComputeContextSwitchesRaw();

            return(FormatContextSwitchResult(result));
        }
예제 #2
0
        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);
        }
예제 #3
0
        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());
        }