예제 #1
0
        public static void FlagD1ReportTime(TimelineEntry entry)
        {
            if (!IsTaskCL(entry))
            {
                return;
            }

            TimelineBuildEntry timelineBuildEntry = entry as TimelineBuildEntry;

            // flag /d1reportTime operates within the front-end and has three sections
            //   - Headers: time spent including headers
            //   - Class Definitions: time spent defining classes
            //   - Function Definitions: time spent defining functions
            // each section ends with a blank line and a Total
            // because of how MSBuild reports messages, we require build to compile each
            // file in a single-threaded fashion or we'd get data mixed up

            IEnumerable <MessageEvent> messages = timelineBuildEntry.BuildEntry.ChildEvents.Where(_ => _ is MessageEvent)
                                                  .Select(_ => _ as MessageEvent);

            // kind of a simplified state machine
            TimelineEntry       currentFrontendEntry = null;
            TimelineEntry       currentSubEntry      = null;
            D1ReportTimeSection currentSection       = D1ReportTimeSection.None;
            int  currentIndentationLevel             = 0;
            bool processEntries = false;

            foreach (MessageEvent message in messages)
            {
                // file compilation started
                Match matchFileStarted = s_CompileFileStart.Match(message.Message);
                if (matchFileStarted.Success)
                {
                    currentFrontendEntry = timelineBuildEntry.ChildEntries.Find(_ => _.Name == matchFileStarted.Value);

                    Debug.Assert(currentFrontendEntry.ChildEntries.Count > 0, "Processing /d1reportTime without an existing front-end child");

                    // first entry is the front-end one, second one (if any) is the back-end one
                    currentSubEntry = currentFrontendEntry.ChildEntries.First();
                    continue;
                }

                // processing /d1reportTime
                if (currentFrontendEntry != null)
                {
                    switch (currentSection)
                    {
                    case D1ReportTimeSection.None:
                    {
                        // look for a new section
                        Match matchSectionHeaders = s_D1ReportTimeSectionHeader.Match(message.Message);
                        if (matchSectionHeaders.Success)
                        {
                            currentSection = D1ReportTimeSection.Headers;

                            // first message starts with two tabs
                            currentIndentationLevel = s_D1ReportTimeEntryBaseIndentation;

                            TimelineEntry headersEntry = new TimelineEntry(matchSectionHeaders.Groups[1].Value, message.Context.NodeId, currentSubEntry.StartTimestamp, message.Timestamp);
                            currentSubEntry.AddChild(headersEntry);
                            currentSubEntry = headersEntry;

                            processEntries = true;

                            continue;
                        }

                        Match matchSectionClasses = s_D1ReportTimeSectionClassDefinition.Match(message.Message);
                        if (matchSectionClasses.Success)
                        {
                            currentSection = D1ReportTimeSection.ClassDefinitions;

                            // first message starts with two tabs
                            currentIndentationLevel = s_D1ReportTimeEntryBaseIndentation;

                            TimelineEntry classesEntry = new TimelineEntry(matchSectionClasses.Groups[1].Value, message.Context.NodeId, currentSubEntry.ChildEntries.Last().EndTimestamp, message.Timestamp);
                            currentSubEntry.AddChild(classesEntry);
                            currentSubEntry = classesEntry;

                            processEntries = true;

                            continue;
                        }

                        Match matchSectionFunctions = s_D1ReportTimeSectionFunctionDefintition.Match(message.Message);
                        if (matchSectionFunctions.Success)
                        {
                            currentSection = D1ReportTimeSection.FunctionDefinitions;

                            // first message starts with two tabs
                            currentIndentationLevel = s_D1ReportTimeEntryBaseIndentation;

                            TimelineEntry classesEntry = new TimelineEntry(matchSectionFunctions.Groups[1].Value, message.Context.NodeId, currentSubEntry.ChildEntries.Last().EndTimestamp, message.Timestamp);
                            currentSubEntry.AddChild(classesEntry);
                            currentSubEntry = classesEntry;

                            processEntries = true;

                            continue;
                        }
                    }
                    break;

                    case D1ReportTimeSection.Headers:
                    case D1ReportTimeSection.ClassDefinitions:
                    case D1ReportTimeSection.FunctionDefinitions:
                    {
                        // get total time spent in this section
                        Match matchTotalTime = s_D1ReportTimeSectionTotal.Match(message.Message);
                        if (matchTotalTime.Success)
                        {
                            double   elapsedTimeFromMessage = Double.Parse(matchTotalTime.Groups[1].Value, CultureInfo.InvariantCulture);
                            TimeSpan elapsedTime            = TimeSpanFromSeconds(elapsedTimeFromMessage);
                            DateTime endTimestamp           = currentSubEntry.StartTimestamp + elapsedTime;

                            currentSubEntry.SetEndTimestamp(endTimestamp);

                            currentSection  = D1ReportTimeSection.None;
                            currentSubEntry = currentSubEntry.Parent;
                            continue;
                        }

                        // block completed?
                        Match matchBlockCompleted = s_D1ReportTimeBlockEnd.Match(message.Message);
                        if (matchBlockCompleted.Success)
                        {
                            if (processEntries)
                            {
                                // pop entries until we get to the top level
                                for (int i = currentIndentationLevel; i > s_D1ReportTimeEntryBaseIndentation; --i)
                                {
                                    currentSubEntry = currentSubEntry.Parent;
                                }

                                processEntries = false;
                            }
                            continue;
                        }

                        if (processEntries)
                        {
                            // match with an element
                            Match matchElement = s_D1ReportTimeEntry.Match(message.Message);
                            if (matchElement.Success)
                            {
                                // \t is a single character
                                int indentationLevel = matchElement.Groups[1].Value.Length;

                                // go to a parent, if needed
                                if (indentationLevel < currentIndentationLevel)
                                {
                                    for (int i = 0; i < currentIndentationLevel - indentationLevel; ++i)
                                    {
                                        currentSubEntry = currentSubEntry.Parent;
                                    }
                                }
                                // move to a child, if needed
                                else if (indentationLevel > currentIndentationLevel)
                                {
                                    currentSubEntry = currentSubEntry.ChildEntries.Last();
                                }

                                // find out the start timestamp
                                DateTime startTimestamp = currentSubEntry.StartTimestamp;
                                if (currentSubEntry.ChildEntries.Count > 0)
                                {
                                    startTimestamp = currentSubEntry.ChildEntries.Last().EndTimestamp;
                                }

                                // find out the end timestamp
                                double   elapsedTimeFromMessage = Double.Parse(matchElement.Groups[3].Value, CultureInfo.InvariantCulture);
                                TimeSpan elapsedTime            = TimeSpanFromSeconds(elapsedTimeFromMessage);
                                DateTime endTimestamp           = startTimestamp + elapsedTime;

                                // build element
                                TimelineEntry elementEntry = new TimelineEntry(matchElement.Groups[2].Value, message.Context.NodeId, startTimestamp, endTimestamp);
                                currentSubEntry.AddChild(elementEntry);

                                currentIndentationLevel = indentationLevel;

                                continue;
                            }
                        }
                    }
                    break;
                    }
                }

                // front-end finished
                Match matchFrontendFinished = s_CompileFrontEndFinish.Match(message.Message);
                if (matchFrontendFinished.Success)
                {
                    currentFrontendEntry = null;
                    currentSubEntry      = null;
                    currentSection       = D1ReportTimeSection.None;
                    continue;
                }
            }
        }
예제 #2
0
        public static void TaskCLSingleThread(TimelineEntry entry)
        {
            // only CL tasks
            if (!IsTaskCL(entry))
            {
                return;
            }

            TimelineBuildEntry timelineBuildEntry = entry as TimelineBuildEntry;

            // single threaded compilations contain a message that multithreaded ones don't
            if (!HasTaskCLSingleThreadMessage(timelineBuildEntry))
            {
                return;
            }

            // because it's single threaded, it will first execute the compiler frontend for all
            // files, then the compiler backend for all files, sequentially
            // so, we have to parse messages and expect frontend ones first, then the special message
            // saying that phase is over, then the backend ones (and maybe cycle to a frontend phase)
            List <TimelineEntry>       compilationEntries = new List <TimelineEntry>();
            IEnumerable <MessageEvent> messages           = timelineBuildEntry.BuildEntry.ChildEvents.Where(_ => _ is MessageEvent)
                                                            .Select(_ => _ as MessageEvent);

            bool isInFrontendPhase = true;

            foreach (MessageEvent message in messages)
            {
                if (isInFrontendPhase)
                {
                    Debug.Assert(!s_CompileBackEndFinish.IsMatch(message.Message));

                    // file compilation started
                    Match matchFileStarted = s_CompileFileStart.Match(message.Message);
                    if (matchFileStarted.Success)
                    {
                        TimelineEntry compilationEntry = new TimelineEntry(matchFileStarted.Value, message.Context.NodeId, message.Timestamp, message.Timestamp);
                        compilationEntries.Add(compilationEntry);

                        compilationEntry.ThreadAffinity.SetParameters(compilationEntry.ThreadAffinity.ThreadId, ThreadAffinity.s_OffsetFromParentPostProcessedEntries, ThreadAffinity.s_OffsetFromParentPostProcessedEntriesIncrement);

                        continue;
                    }

                    // front-end compilation finished
                    Match matchFrontendFinished = s_CompileFrontEndFinish.Match(message.Message);
                    if (matchFrontendFinished.Success)
                    {
                        TimelineEntry compilationEntry = compilationEntries.Find(_ => _.Name == matchFrontendFinished.Groups[3].Value.Split('\\').Last());
                        if (compilationEntry != null)
                        {
                            double   elapsedTimeFromMessage = Double.Parse(matchFrontendFinished.Groups[2].Value, CultureInfo.InvariantCulture);
                            TimeSpan elapsedTime            = TimeSpanFromSeconds(elapsedTimeFromMessage);
                            DateTime startTimestamp         = message.Timestamp - elapsedTime;
                            if (startTimestamp < compilationEntry.StartTimestamp)
                            {
                                startTimestamp = compilationEntry.StartTimestamp;
                            }

                            // add a front-end entry
                            TimelineEntry frontend = new TimelineEntry(matchFrontendFinished.Groups[1].Value, message.Context.NodeId, startTimestamp, message.Timestamp);
                            compilationEntry.AddChild(frontend);
                            compilationEntry.SetEndTimestamp(message.Timestamp);
                        }

                        continue;
                    }

                    if (message.Message == s_TaskCLSingleThreadFrontEndFinishedMessage)
                    {
                        isInFrontendPhase = false;
                    }
                }
                else
                {
                    Debug.Assert(!s_CompileFrontEndFinish.IsMatch(message.Message));

                    // back-end compilation finished
                    Match matchBackendFinished = s_CompileBackEndFinish.Match(message.Message);
                    if (matchBackendFinished.Success)
                    {
                        Debug.Assert(compilationEntries.Count > 0);

                        // create new entry as parent of the back-end entry
                        TimelineEntry compilationEntry = new TimelineEntry(matchBackendFinished.Groups[3].Value.Split('\\').Last(), message.Context.NodeId, compilationEntries.Last().EndTimestamp, message.Timestamp);
                        compilationEntries.Add(compilationEntry);

                        compilationEntry.ThreadAffinity.SetParameters(compilationEntry.ThreadAffinity.ThreadId, ThreadAffinity.s_OffsetFromParentPostProcessedEntries, ThreadAffinity.s_OffsetFromParentPostProcessedEntriesIncrement);

                        // add a back-end entry
                        double   elapsedTimeFromMessage = Double.Parse(matchBackendFinished.Groups[2].Value, CultureInfo.InvariantCulture);
                        TimeSpan elapsedTime            = TimeSpanFromSeconds(elapsedTimeFromMessage);
                        DateTime startTimestamp         = message.Timestamp - elapsedTime;
                        if (startTimestamp < compilationEntry.StartTimestamp)
                        {
                            startTimestamp = compilationEntry.StartTimestamp;
                        }

                        TimelineEntry backend = new TimelineEntry(matchBackendFinished.Groups[1].Value, message.Context.NodeId, startTimestamp, message.Timestamp);
                        compilationEntry.AddChild(backend);

                        continue;
                    }

                    if (message.Message == s_TaskCLSingleThreadFrontEndStartedMessage)
                    {
                        isInFrontendPhase = true;
                    }
                }
            }

            // add them all to the CL task
            compilationEntries.ForEach(timelineBuildEntry.AddChild);
        }
예제 #3
0
        public static void TaskCLMultiThread(TimelineEntry entry)
        {
            if (!IsTaskCL(entry))
            {
                return;
            }

            TimelineBuildEntry timelineBuildEntry = entry as TimelineBuildEntry;

            // single threaded compilations contain a message that multithreaded ones don't
            if (HasTaskCLSingleThreadMessage(timelineBuildEntry))
            {
                return;
            }

            // because these messages aren't related to each other in any way other than parsing messages,
            // we'll be keeping a list of timeline entries which will open/close as the messages are processed
            List <TimelineEntry>       compilationEntries = new List <TimelineEntry>();
            IEnumerable <MessageEvent> messages           = timelineBuildEntry.BuildEntry.ChildEvents.Where(_ => _ is MessageEvent)
                                                            .Select(_ => _ as MessageEvent);

            foreach (MessageEvent message in messages)
            {
                // file compilation started
                Match matchFileStarted = s_CompileFileStart.Match(message.Message);
                if (matchFileStarted.Success)
                {
                    // with /Wall flag enabled some warnings will be mixed up with this kind of message
                    // meaning we may not match the regex and won't add the entry

                    TimelineEntry compilationEntry = new TimelineEntry(matchFileStarted.Value, message.Context.NodeId, message.Timestamp, message.Timestamp);
                    compilationEntries.Add(compilationEntry);

                    compilationEntry.ThreadAffinity.SetParameters(compilationEntry.ThreadAffinity.ThreadId, ThreadAffinity.s_OffsetFromParentPostProcessedEntries, ThreadAffinity.s_OffsetFromParentPostProcessedEntriesIncrement);

                    continue;
                }

                // front-end compilation finished
                Match matchFrontendFinished = s_CompileFrontEndFinish.Match(message.Message);
                if (matchFrontendFinished.Success)
                {
                    // with /Wall flag enabled some warnings will be mixed up with this kind of message
                    // meaning we may not match the regex and won't add the entry
                    // we may not even find the parent compilation entry

                    TimelineEntry compilationEntry = compilationEntries.Find(_ => _.Name == matchFrontendFinished.Groups[3].Value.Split('\\').Last());
                    if (compilationEntry != null)
                    {
                        double   elapsedTimeFromMessage = Double.Parse(matchFrontendFinished.Groups[2].Value, CultureInfo.InvariantCulture);
                        TimeSpan elapsedTime            = TimeSpanFromSeconds(elapsedTimeFromMessage);
                        DateTime startTimestamp         = message.Timestamp - elapsedTime;
                        if (startTimestamp < compilationEntry.StartTimestamp)
                        {
                            startTimestamp = compilationEntry.StartTimestamp;
                        }

                        // add a front-end entry
                        TimelineEntry frontend = new TimelineEntry(matchFrontendFinished.Groups[1].Value, message.Context.NodeId, startTimestamp, message.Timestamp);
                        compilationEntry.AddChild(frontend);

                        // just in case the back-end fails, update entry's timestamp
                        compilationEntry.SetEndTimestamp(message.Timestamp);
                    }

                    continue;
                }

                // back-end compilation finished
                Match matchBackendFinished = s_CompileBackEndFinish.Match(message.Message);
                if (matchBackendFinished.Success)
                {
                    // with /Wall flag enabled some warnings will be mixed up with this kind of message
                    // meaning we may not match the regex and won't add the entry
                    // we may not even find the parent compilation entry nor the frontend sibling

                    TimelineEntry compilationEntry = compilationEntries.Find(_ => _.Name == matchBackendFinished.Groups[3].Value.Split('\\').Last());
                    if (compilationEntry != null)
                    {
                        TimelineEntry frontendEntry = compilationEntry.ChildEntries.FirstOrDefault();

                        double   elapsedTimeFromMessage = Double.Parse(matchBackendFinished.Groups[2].Value, CultureInfo.InvariantCulture);
                        TimeSpan elapsedTime            = TimeSpanFromSeconds(elapsedTimeFromMessage);
                        DateTime startTimestamp         = message.Timestamp - elapsedTime;

                        if (frontendEntry != null)
                        {
                            if (startTimestamp < frontendEntry.EndTimestamp)
                            {
                                startTimestamp = frontendEntry.EndTimestamp;
                            }
                        }
                        else if (startTimestamp < compilationEntry.StartTimestamp)
                        {
                            startTimestamp = compilationEntry.StartTimestamp;
                        }

                        // add a back-end entry
                        TimelineEntry backend = new TimelineEntry(matchBackendFinished.Groups[1].Value, message.Context.NodeId, startTimestamp, message.Timestamp);
                        compilationEntry.AddChild(backend);

                        // complete compilation entry
                        compilationEntry.SetEndTimestamp(message.Timestamp);
                    }

                    continue;
                }
            }

            // add them all to the CL task
            compilationEntries.ForEach(timelineBuildEntry.AddChild);
        }