File: Evaluation\Profiler\ProfilerResultPrettyPrinter.cs
Web Access
Project: ..\..\..\src\Build\Microsoft.Build.csproj (Microsoft.Build)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework.Profiler;
 
#nullable disable
 
namespace Microsoft.Build.Evaluation
{
    /// <summary>
    /// Pretty prints a profiled result to a variety of formats
    /// </summary>
    internal sealed class ProfilerResultPrettyPrinter
    {
        /// <summary>
        /// Gets a profiled result in a markdown-like form.
        /// </summary>
        public static string GetMarkdownContent(ProfilerResult result)
        {
            return GetContent(result, new EvaluationLocationMarkdownPrettyPrinter());
        }
 
        /// <summary>
        /// Gets a profiled result in a tab separated value form.
        /// </summary>
        public static string GetTsvContent(ProfilerResult result)
        {
            return GetContent(result, new EvaluationLocationTabSeparatedPrettyPrinter());
        }
 
        private static string GetContent(ProfilerResult result, EvaluationLocationPrettyPrinterBase evaluationLocationPrinter)
        {
            var stringBuilder = new StringBuilder();
 
            evaluationLocationPrinter.AppendHeader(stringBuilder);
 
            var profiledLocations = result.ProfiledLocations;
 
            // If there are no profiled locations, then just return
            if (profiledLocations.Count == 0)
            {
                return stringBuilder.ToString();
            }
 
            var evaluationPasses = profiledLocations.Where(l => l.Key.IsEvaluationPass)
                                                  .OrderBy(l => l.Key.EvaluationPass);
 
            var orderedLocations = profiledLocations.Where(l => !l.Key.IsEvaluationPass)
                                                  .OrderByDescending(l => l.Value.ExclusiveTime);
 
            // All evaluation passes go first
            TimeSpan? totalTime = null;
            foreach (var pair in evaluationPasses)
            {
                var time = pair.Value;
                var location = pair.Key;
 
                if (totalTime == null)
                {
                    totalTime = time.InclusiveTime;
                }
 
                evaluationLocationPrinter.AppendLocation(stringBuilder, totalTime.Value, location, time);
            }
 
            Debug.Assert(totalTime != null, "There should be at least one evaluation pass result");
 
            // All non-evaluation passes go later
            foreach (var pair in orderedLocations)
            {
                var time = pair.Value;
                var location = pair.Key;
 
                evaluationLocationPrinter.AppendLocation(stringBuilder, totalTime.Value, location, time);
            }
 
            return stringBuilder.ToString();
        }
    }
}