Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add text justification style #2410

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 14 additions & 14 deletions src/BenchmarkDotNet/Exporters/MarkdownExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ public enum MarkdownHighlightStrategy
[PublicAPI] protected string CodeBlockStart = "```";
[PublicAPI] protected string CodeBlockEnd = "```";
[PublicAPI] protected MarkdownHighlightStrategy StartOfGroupHighlightStrategy = MarkdownHighlightStrategy.None;
[PublicAPI] protected string TableHeaderSeparator = " |";
[PublicAPI] protected string TableColumnSeparator = " |";
[PublicAPI] protected string TableHeaderSeparator = " | ";
[PublicAPI] protected string TableColumnSeparator = " | ";
[PublicAPI] protected bool UseHeaderSeparatingRow = true;
[PublicAPI] protected bool ColumnsStartWithSeparator;
[PublicAPI] protected string BoldMarkupFormat = "**{0}**";
Expand Down Expand Up @@ -166,11 +166,13 @@ private void PrintTable(SummaryTable table, ILogger logger)
{
if (ColumnsStartWithSeparator)
{
logger.WriteStatistic(TableHeaderSeparator.TrimStart());
logger.WriteStatistic(TableHeaderSeparator.TrimStart().TrimEnd() + "-");
}

logger.WriteLineStatistic(string.Join("",
table.Columns.Where(c => c.NeedToShow).Select(column => new string('-', column.Width) + GetJustificationIndicator(column.Justify) + "|")));
table.Columns.Where(c => c.NeedToShow).Select(column =>
new string('-', column.Width - 1) + GetHeaderSeparatorIndicator(column.OriginalColumn.IsNumeric) +
GetHeaderSeparatorColumnDivider(column.Index, table.ColumnCount))));
}

int rowCounter = 0;
Expand Down Expand Up @@ -202,17 +204,15 @@ private void PrintTable(SummaryTable table, ILogger logger)
}
}

private static string GetJustificationIndicator(SummaryTable.SummaryTableColumn.TextJustification textJustification)
private static string GetHeaderSeparatorIndicator(bool isNumeric)
{
switch (textJustification)
{
case SummaryTable.SummaryTableColumn.TextJustification.Left:
return " ";
case SummaryTable.SummaryTableColumn.TextJustification.Right:
return ":";
default:
return " ";
}
return isNumeric ? ":" : " ";
}

private static string GetHeaderSeparatorColumnDivider(int columnIndex, int columnCount)
{
var isLastColumn = columnIndex != columnCount - 1;
return isLastColumn ? "|-" : "|";
}
}
}
20 changes: 19 additions & 1 deletion src/BenchmarkDotNet/Helpers/HashCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,23 @@ public static int Combine<T1>(T1 value1)
return hashCode;
}

public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7,
T8 value8, T9 value9, T10 value10)
{
int hashCode = 0;
hashCode = Hash(hashCode, value1);
hashCode = Hash(hashCode, value2);
hashCode = Hash(hashCode, value3);
hashCode = Hash(hashCode, value4);
hashCode = Hash(hashCode, value5);
hashCode = Hash(hashCode, value6);
hashCode = Hash(hashCode, value7);
hashCode = Hash(hashCode, value8);
hashCode = Hash(hashCode, value9);
hashCode = Hash(hashCode, value10);
return hashCode;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int Hash<T>(int hashCode, T value)
{
Expand All @@ -128,7 +145,8 @@ private static int Hash<T>(int hashCode, T value, IEqualityComparer<T> comparer)
}

#pragma warning disable CS0809 // Obsolete member 'HashCode.GetHashCode()' overrides non-obsolete member 'object.GetHashCode()'
[Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", error: true)]
[Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.",
error: true)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => throw new NotSupportedException();

Expand Down
5 changes: 3 additions & 2 deletions src/BenchmarkDotNet/Reports/Summary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public class Summary
TimeSpan totalTime,
CultureInfo cultureInfo,
ImmutableArray<ValidationError> validationErrors,
ImmutableArray<IColumnHidingRule> columnHidingRules)
ImmutableArray<IColumnHidingRule> columnHidingRules,
SummaryStyle summaryStyle = null)
{
Title = title;
ResultsDirectoryPath = resultsDirectoryPath;
Expand All @@ -64,7 +65,7 @@ public class Summary
BenchmarksCases = Orderer.GetSummaryOrder(reports.Select(report => report.BenchmarkCase).ToImmutableArray(), this).ToImmutableArray(); // we sort it first
Reports = BenchmarksCases.Select(b => ReportMap[b]).ToImmutableArray(); // we use sorted collection to re-create reports list
BaseliningStrategy = BaseliningStrategy.Create(BenchmarksCases);
Style = GetConfiguredSummaryStyleOrDefaultOne(BenchmarksCases).WithCultureInfo(cultureInfo);
Style = (summaryStyle ?? GetConfiguredSummaryStyleOrDefaultOne(BenchmarksCases)).WithCultureInfo(cultureInfo);
Table = GetTable(Style);
AllRuntimes = BuildAllRuntimes(HostEnvironmentInfo, Reports);
}
Expand Down
41 changes: 30 additions & 11 deletions src/BenchmarkDotNet/Reports/SummaryStyle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Helpers;
using Perfolizer.Horology;
using static BenchmarkDotNet.Reports.SummaryTable.SummaryTableColumn;

// ReSharper disable MemberCanBePrivate.Global

namespace BenchmarkDotNet.Reports
{
public class SummaryStyle : IEquatable<SummaryStyle>
{
public static readonly SummaryStyle Default = new SummaryStyle(DefaultCultureInfo.Instance, printUnitsInHeader: false, printUnitsInContent: true, printZeroValuesInContent: false, sizeUnit: null, timeUnit: null);
public static readonly SummaryStyle Default = new SummaryStyle(DefaultCultureInfo.Instance, printUnitsInHeader: false, printUnitsInContent: true,
printZeroValuesInContent: false, sizeUnit: null, timeUnit: null);

internal const int DefaultMaxParameterColumnWidth = 15 + 5; // 5 is for postfix " [15]"

public bool PrintUnitsInHeader { get; }
Expand All @@ -24,8 +27,12 @@ public class SummaryStyle : IEquatable<SummaryStyle>

public RatioStyle RatioStyle { get; }

public TextJustification TextColumnJustification { get; }
public TextJustification NumericColumnJustification { get; }

public SummaryStyle(CultureInfo? cultureInfo, bool printUnitsInHeader, SizeUnit sizeUnit, TimeUnit timeUnit, bool printUnitsInContent = true,
bool printZeroValuesInContent = false, int maxParameterColumnWidth = DefaultMaxParameterColumnWidth, RatioStyle ratioStyle = RatioStyle.Value)
bool printZeroValuesInContent = false, int maxParameterColumnWidth = DefaultMaxParameterColumnWidth, RatioStyle ratioStyle = RatioStyle.Value,
TextJustification textColumnJustification = TextJustification.Left, TextJustification numericColumnJustification = TextJustification.Right)
{
if (maxParameterColumnWidth < DefaultMaxParameterColumnWidth)
throw new ArgumentOutOfRangeException(nameof(maxParameterColumnWidth), $"{DefaultMaxParameterColumnWidth} is the minimum.");
Expand All @@ -35,29 +42,37 @@ public class SummaryStyle : IEquatable<SummaryStyle>
PrintUnitsInContent = printUnitsInContent;
SizeUnit = sizeUnit;
TimeUnit = timeUnit;
PrintZeroValuesInContent = printZeroValuesInContent;
MaxParameterColumnWidth = maxParameterColumnWidth;
RatioStyle = ratioStyle;
CodeSizeUnit = SizeUnit.B;
PrintZeroValuesInContent = printZeroValuesInContent;
TextColumnJustification = textColumnJustification;
NumericColumnJustification = numericColumnJustification;
}

public SummaryStyle WithTimeUnit(TimeUnit timeUnit)
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, SizeUnit, timeUnit, PrintUnitsInContent, PrintZeroValuesInContent, MaxParameterColumnWidth, RatioStyle);
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, SizeUnit, timeUnit, PrintUnitsInContent, PrintZeroValuesInContent, MaxParameterColumnWidth,
RatioStyle, TextColumnJustification, NumericColumnJustification);

public SummaryStyle WithSizeUnit(SizeUnit sizeUnit)
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, sizeUnit, TimeUnit, PrintUnitsInContent, PrintZeroValuesInContent, MaxParameterColumnWidth, RatioStyle);
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, sizeUnit, TimeUnit, PrintUnitsInContent, PrintZeroValuesInContent, MaxParameterColumnWidth,
RatioStyle, TextColumnJustification, NumericColumnJustification);

public SummaryStyle WithZeroMetricValuesInContent()
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, SizeUnit, TimeUnit, PrintUnitsInContent, printZeroValuesInContent: true, MaxParameterColumnWidth, RatioStyle);
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, SizeUnit, TimeUnit, PrintUnitsInContent, printZeroValuesInContent: true,
MaxParameterColumnWidth, RatioStyle, TextColumnJustification, NumericColumnJustification);

public SummaryStyle WithMaxParameterColumnWidth(int maxParameterColumnWidth)
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, SizeUnit, TimeUnit, PrintUnitsInContent, PrintZeroValuesInContent, maxParameterColumnWidth, RatioStyle);
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, SizeUnit, TimeUnit, PrintUnitsInContent, PrintZeroValuesInContent, maxParameterColumnWidth,
RatioStyle, TextColumnJustification, NumericColumnJustification);

public SummaryStyle WithCultureInfo(CultureInfo cultureInfo)
=> new SummaryStyle(cultureInfo, PrintUnitsInHeader, SizeUnit, TimeUnit, PrintUnitsInContent, PrintZeroValuesInContent, MaxParameterColumnWidth, RatioStyle);
=> new SummaryStyle(cultureInfo, PrintUnitsInHeader, SizeUnit, TimeUnit, PrintUnitsInContent, PrintZeroValuesInContent, MaxParameterColumnWidth,
RatioStyle, TextColumnJustification, NumericColumnJustification);

public SummaryStyle WithRatioStyle(RatioStyle ratioStyle)
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, SizeUnit, TimeUnit, PrintUnitsInContent, PrintZeroValuesInContent, MaxParameterColumnWidth, ratioStyle);
=> new SummaryStyle(CultureInfo, PrintUnitsInHeader, SizeUnit, TimeUnit, PrintUnitsInContent, PrintZeroValuesInContent, MaxParameterColumnWidth,
ratioStyle, TextColumnJustification, NumericColumnJustification);

public bool Equals(SummaryStyle other)
{
Expand All @@ -73,7 +88,9 @@ public bool Equals(SummaryStyle other)
&& Equals(CodeSizeUnit, other.CodeSizeUnit)
&& Equals(TimeUnit, other.TimeUnit)
&& MaxParameterColumnWidth == other.MaxParameterColumnWidth
&& RatioStyle == other.RatioStyle;
&& RatioStyle == other.RatioStyle
&& TextColumnJustification == other.TextColumnJustification
&& NumericColumnJustification == other.NumericColumnJustification;
}

public override bool Equals(object obj) => obj is SummaryStyle summary && Equals(summary);
Expand All @@ -87,7 +104,9 @@ public bool Equals(SummaryStyle other)
CodeSizeUnit,
TimeUnit,
MaxParameterColumnWidth,
RatioStyle);
RatioStyle,
TextColumnJustification,
NumericColumnJustification);

public static bool operator ==(SummaryStyle left, SummaryStyle right) => Equals(left, right);

Expand Down
5 changes: 2 additions & 3 deletions src/BenchmarkDotNet/Reports/SummaryTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ internal SummaryTable(Summary summary, SummaryStyle style = null)
.Select(r => r.GcStats.GetBytesAllocatedPerOperation(r.BenchmarkCase).Value)
.ToArray()));
}
EffectiveSummaryStyle = style;

var columns = summary.GetColumns();
ColumnCount = columns.Length;
Expand Down Expand Up @@ -96,8 +97,6 @@ internal SummaryTable(Summary summary, SummaryStyle style = null)
bool hide = summary.ColumnHidingRules.Any(rule => rule.NeedToHide(column));
Columns[i] = new SummaryTableColumn(this, i, column, hide);
}

EffectiveSummaryStyle = style;
}

public class SummaryTableColumn
Expand All @@ -123,7 +122,7 @@ public SummaryTableColumn(SummaryTable table, int index, IColumn column, bool hi
IsDefault = table.IsDefault[index];
OriginalColumn = column;

Justify = column.IsNumeric ? TextJustification.Right : TextJustification.Left;
Justify = column.IsNumeric ? table.EffectiveSummaryStyle.NumericColumnJustification : table.EffectiveSummaryStyle.TextColumnJustification;

bool needToShow = column.AlwaysShow || Content.Distinct().Count() > 1;
NeedToShow = !hide && needToShow;
Expand Down
35 changes: 29 additions & 6 deletions src/BenchmarkDotNet/Reports/SummaryTableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public static void PrintLine(this SummaryTable table, string[] line, ILogger log
}

public static void PrintLine(this SummaryTable table, string[] line, ILogger logger, string leftDel, string rightDel,
bool highlightRow, bool startOfGroup, MarkdownExporter.MarkdownHighlightStrategy startOfGroupHighlightStrategy, string boldMarkupFormat, bool escapeHtml)
bool highlightRow, bool startOfGroup, MarkdownExporter.MarkdownHighlightStrategy startOfGroupHighlightStrategy, string boldMarkupFormat,
bool escapeHtml)
{
for (int columnIndex = 0; columnIndex < table.ColumnCount; columnIndex++)
{
Expand Down Expand Up @@ -82,23 +83,45 @@ public static void PrintLine(this SummaryTable table, string[] line, ILogger log
private static string BuildStandardText(SummaryTable table, string[] line, string leftDel, string rightDel, int columnIndex)
{
var buffer = GetClearBuffer();
var columnJustification = table.Columns[columnIndex].Justify;

buffer.Append(leftDel);
PadLeft(table, line, leftDel, rightDel, columnIndex, buffer);
if (columnJustification == SummaryTable.SummaryTableColumn.TextJustification.Right)
{
AddPadding(table, line, leftDel, rightDel, columnIndex, buffer);
}

buffer.Append(line[columnIndex]);
buffer.Append(rightDel);

if (columnJustification == SummaryTable.SummaryTableColumn.TextJustification.Left)
{
AddPadding(table, line, leftDel, rightDel, columnIndex, buffer);
}
var isLastColumn = columnIndex == table.ColumnCount - 1;
buffer.Append(isLastColumn ? rightDel.TrimEnd() : rightDel);

return buffer.ToString();
}

private static string BuildBoldText(SummaryTable table, string[] line, string leftDel, string rightDel, int columnIndex, string boldMarkupFormat)
{
var buffer = GetClearBuffer();
var columnJustification = table.Columns[columnIndex].Justify;

buffer.Append(leftDel);
PadLeft(table, line, leftDel, rightDel, columnIndex, buffer);
if (columnJustification == SummaryTable.SummaryTableColumn.TextJustification.Right)
{
AddPadding(table, line, leftDel, rightDel, columnIndex, buffer);
}

buffer.AppendFormat(boldMarkupFormat, line[columnIndex]);
buffer.Append(rightDel);

if (columnJustification == SummaryTable.SummaryTableColumn.TextJustification.Left)
{
AddPadding(table, line, leftDel, rightDel, columnIndex, buffer);
}
var isLastColumn = columnIndex == table.ColumnCount - 1;
buffer.Append(isLastColumn ? rightDel.TrimEnd() : rightDel);

return buffer.ToString();
}
Expand All @@ -116,7 +139,7 @@ private static StringBuilder GetClearBuffer()
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void PadLeft(SummaryTable table, string[] line, string leftDel, string rightDel, int columnIndex, StringBuilder buffer)
private static void AddPadding(SummaryTable table, string[] line, string leftDel, string rightDel, int columnIndex, StringBuilder buffer)
{
const char space = ' ';
const int extraWidth = 2; // " |".Length is not included in the column's Width
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ Frequency: 2531248 Hz, Resolution: 395.0620 ns, Timer: TSC
DefaultJob : extra output line


Method | ParamProperty | Mean | Error | StdDev |
---------- |-------------- |---------:|--------:|--------:|
Benchmark | False | 102.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | True | 202.0 ns | 6.09 ns | 1.58 ns | ^
Method | ParamProperty | Mean | Error | StdDev |
timcassell marked this conversation as resolved.
Show resolved Hide resolved
--------- |-------------- |---------:|--------:|--------:|
Benchmark | False | 102.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | True | 202.0 ns | 6.09 ns | 1.58 ns | ^
timcassell marked this conversation as resolved.
Show resolved Hide resolved

Errors: 0
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Frequency: 2531248 Hz, Resolution: 395.0620 ns, Timer: TSC
DefaultJob : extra output line


Method | ParamProperty | Mean | Error | StdDev |
---------- |-------------- |---------:|--------:|--------:|
Benchmark | A | 102.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | B | 202.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | C | 302.0 ns | 6.09 ns | 1.58 ns | ^
Method | ParamProperty | Mean | Error | StdDev |
--------- |-------------- |---------:|--------:|--------:|
Benchmark | A | 102.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | B | 202.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | C | 302.0 ns | 6.09 ns | 1.58 ns | ^

Errors: 0
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Frequency: 2531248 Hz, Resolution: 395.0620 ns, Timer: TSC
DefaultJob : extra output line


Method | ParamProperty | Mean | Error | StdDev |
---------- |-------------- |---------:|--------:|--------:|
Benchmark | ? | 102.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | False | 202.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | True | 302.0 ns | 6.09 ns | 1.58 ns | ^
Method | ParamProperty | Mean | Error | StdDev |
--------- |-------------- |---------:|--------:|--------:|
Benchmark | ? | 102.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | False | 202.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | True | 302.0 ns | 6.09 ns | 1.58 ns | ^

Errors: 0
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ Frequency: 2531248 Hz, Resolution: 395.0620 ns, Timer: TSC
DefaultJob : extra output line


Method | ParamProperty | Mean | Error | StdDev |
---------- |-------------- |---------:|--------:|--------:|
Benchmark | ? | 102.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | A | 202.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | B | 302.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | C | 402.0 ns | 6.09 ns | 1.58 ns | ^
Method | ParamProperty | Mean | Error | StdDev |
--------- |-------------- |---------:|--------:|--------:|
Benchmark | ? | 102.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | A | 202.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | B | 302.0 ns | 6.09 ns | 1.58 ns | ^
Benchmark | C | 402.0 ns | 6.09 ns | 1.58 ns | ^

Errors: 0