| File: Evaluation\Profiler\EvaluationLocationPrettyPrinterBase.cs | Web Access |
| Project: src\msbuild\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.Text; using Microsoft.Build.Framework.Profiler; #nullable disable namespace Microsoft.Build.Evaluation { /// <summary> /// Pretty prints an evaluation location with its associated profiled location /// </summary> internal abstract class EvaluationLocationPrettyPrinterBase { /// <summary> /// Appends the header of all the locations to the string builder /// </summary> /// <param name="stringBuilder"></param> internal abstract void AppendHeader(StringBuilder stringBuilder); /// <summary> /// Appends a pretty printed location with its associated profiled data /// </summary> internal abstract void AppendLocation(StringBuilder stringBuilder, TimeSpan totalTime, EvaluationLocation evaluationLocation, ProfiledLocation profiledLocation); /// <summary> /// Normalizes the expression returned by <see cref="GetElementOrConditionText"/> /// </summary> protected abstract string NormalizeExpression(string description, EvaluationLocationKind kind); /// <nodoc/> protected static double GetMilliseconds(TimeSpan timeSpan) { return Math.Round(timeSpan.TotalMilliseconds, 0, MidpointRounding.AwayFromZero); } /// <nodoc/> protected static double GetPercentage(TimeSpan total, TimeSpan time) { var percentage = (time.TotalMilliseconds / total.TotalMilliseconds) * 100; return Math.Round(percentage, 1, MidpointRounding.AwayFromZero); } /// <nodoc/> protected static string GetElementOrConditionText(string description, EvaluationLocationKind kind) { if (description == null) { return null; } if (kind == EvaluationLocationKind.Condition) { return $"Condition=\"{description}\")"; } if (kind == EvaluationLocationKind.Glob) { return $"Glob=\"{description}\")"; } var outerXml = description; outerXml = outerXml.Replace(@"xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""", ""); var newLineIndex = outerXml.AsSpan().IndexOfAny('\r', '\n'); return newLineIndex == -1 ? outerXml : outerXml.Remove(newLineIndex); } /// <summary> /// Appends a default header with a given separator /// </summary> protected void AppendDefaultHeaderWithSeparator(StringBuilder stringBuilder, string separator) { stringBuilder.Append("Id").Append(separator) .Append("ParentId").Append(separator) .Append("Pass").Append(separator) .Append("File").Append(separator) .Append("Line #").Append(separator) .Append("Expression").Append(separator) .Append("Inc (ms)").Append(separator) .Append("Inc (%)").Append(separator) .Append("Exc (ms)").Append(separator) .Append("Exc (%)").Append(separator) .Append('#').Append(separator) .Append("Kind").Append(separator) .Append("Bug").AppendLine(); } /// <summary> /// Appends a default representation of an evaluation location with a given separator /// </summary> protected void AppendDefaultLocationWithSeparator(StringBuilder stringBuilder, TimeSpan totalTime, EvaluationLocation evaluationLocation, ProfiledLocation profiledLocation, string separator) { stringBuilder.AppendLine(string.Join(separator, evaluationLocation.Id, evaluationLocation.ParentId?.ToString() ?? string.Empty, evaluationLocation.EvaluationPassDescription, evaluationLocation.File == null ? string.Empty : System.IO.Path.GetFileName(evaluationLocation.File), evaluationLocation.Line?.ToString() ?? string.Empty, NormalizeExpression(evaluationLocation.ElementDescription, evaluationLocation.Kind) ?? string.Empty, GetMilliseconds(profiledLocation.InclusiveTime), $"{GetPercentage(totalTime, profiledLocation.InclusiveTime)}%", GetMilliseconds(profiledLocation.ExclusiveTime), $"{GetPercentage(totalTime, profiledLocation.ExclusiveTime)}%", profiledLocation.NumberOfHits, evaluationLocation.Kind + separator)); } } }