mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Reduce allocations in TableWriter (#6648)
* [Feature] Reduce allocations in TableWriter * Revert iterator ReadOnlySpan is not supported in iterators * Use columnsThresHold with stackalloc
This commit is contained in:
@@ -744,8 +744,8 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In cases like implicit remoting, there is no console so reading the console width results in an exception.
|
||||
/// Instead of handling exception every time we cache this value to increase performance.
|
||||
/// In cases like implicit remoting, there is no console so reading the console width results in an exception.
|
||||
/// Instead of handling exception every time we cache this value to increase performance.
|
||||
/// </summary>
|
||||
static private bool _noConsole = false;
|
||||
|
||||
@@ -940,6 +940,8 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
{
|
||||
TableFormattingHint tableHint = this.InnerCommand.RetrieveFormattingHint() as TableFormattingHint;
|
||||
int[] columnWidthsHint = null;
|
||||
// We expect that console width is less then 120.
|
||||
const int columnsThresHold = 120;
|
||||
|
||||
if (tableHint != null)
|
||||
{
|
||||
@@ -955,10 +957,10 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
}
|
||||
|
||||
// create arrays for widths and alignment
|
||||
int[] columnWidths = new int[columns];
|
||||
int[] alignment = new int[columns];
|
||||
int k = 0;
|
||||
Span<int> columnWidths = columns < columnsThresHold ? stackalloc int[columns] : new int[columns];
|
||||
Span<int> alignment = columns < columnsThresHold ? stackalloc int[columns] : new int[columns];
|
||||
|
||||
int k = 0;
|
||||
foreach (TableColumnInfo tci in this.CurrentTableHeaderInfo.tableColumnInfoList)
|
||||
{
|
||||
columnWidths[k] = (columnWidthsHint != null) ? columnWidthsHint[k] : tci.width;
|
||||
@@ -1006,7 +1008,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
|
||||
// need to make sure we have matching counts: the header count will have to prevail
|
||||
string[] values = new string[headerColumns];
|
||||
int[] alignment = new int[headerColumns];
|
||||
Span<int> alignment = stackalloc int[headerColumns];
|
||||
|
||||
int fieldCount = tre.formatPropertyFieldList.Count;
|
||||
|
||||
@@ -1168,8 +1170,8 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
_buffer = new StringValuesBuffer(itemsPerRow);
|
||||
|
||||
// initialize the writer
|
||||
int[] columnWidths = new int[itemsPerRow];
|
||||
int[] alignment = new int[itemsPerRow];
|
||||
Span<int> columnWidths = stackalloc int[itemsPerRow];
|
||||
Span<int> alignment = stackalloc int[itemsPerRow];
|
||||
|
||||
for (int k = 0; k < itemsPerRow; k++)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
{
|
||||
/// <summary>
|
||||
@@ -29,7 +31,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// with column elimination, starting from the right most column
|
||||
/// </summary>
|
||||
/// <param name="columnWidths">array of column widths to appropriately size</param>
|
||||
internal void CalculateColumnWidths(int[] columnWidths)
|
||||
internal void CalculateColumnWidths(Span<int> columnWidths)
|
||||
{
|
||||
if (AssignColumnWidths(columnWidths))
|
||||
{
|
||||
@@ -47,7 +49,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// </summary>
|
||||
/// <param name="columnWidths">columns to process</param>
|
||||
/// <returns>true if there was a fit, false if there is need for trimming</returns>
|
||||
private bool AssignColumnWidths(int[] columnWidths)
|
||||
private bool AssignColumnWidths(Span<int> columnWidths)
|
||||
{
|
||||
// run a quick check to see if all the columns have a specified width,
|
||||
// if so, we are done
|
||||
@@ -127,7 +129,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// trim columns if the total column width is too much for the screen.
|
||||
/// </summary>
|
||||
/// <param name="columnWidths">column widths to trim</param>
|
||||
private void TrimToFit(int[] columnWidths)
|
||||
private void TrimToFit(Span<int> columnWidths)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@@ -166,7 +168,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// </summary>
|
||||
/// <param name="columnWidths">column widths array</param>
|
||||
/// <returns></returns>
|
||||
private int CurrentTableWidth(int[] columnWidths)
|
||||
private int CurrentTableWidth(Span<int> columnWidths)
|
||||
{
|
||||
int sum = 0;
|
||||
int visibleColumns = 0;
|
||||
@@ -188,7 +190,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// </summary>
|
||||
/// <param name="columnWidths">column widths array</param>
|
||||
/// <returns>index of the last visible column, -1 if none</returns>
|
||||
private static int GetLastVisibleColumn(int[] columnWidths)
|
||||
private static int GetLastVisibleColumn(Span<int> columnWidths)
|
||||
{
|
||||
for (int k = 0; k < columnWidths.Length; k++)
|
||||
{
|
||||
|
||||
@@ -700,12 +700,16 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
internal static string TruncateAtNewLine(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s))
|
||||
return s;
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int lineBreak = s.IndexOfAny(s_lineBreakChars);
|
||||
|
||||
if (lineBreak < 0)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
return s.Substring(0, lineBreak) + PSObjectHelper.ellipses;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Management.Automation.Internal;
|
||||
using System.Text;
|
||||
@@ -75,7 +77,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
/// <param name="columnWidths">array of specified column widths</param>
|
||||
/// <param name="alignment">array of alignment flags</param>
|
||||
/// <param name="suppressHeader">if true, suppress header printing</param>
|
||||
internal void Initialize(int leftMarginIndent, int screenColumns, int[] columnWidths, int[] alignment, bool suppressHeader)
|
||||
internal void Initialize(int leftMarginIndent, int screenColumns, Span<int> columnWidths, ReadOnlySpan<int> alignment, bool suppressHeader)
|
||||
{
|
||||
//Console.WriteLine(" 1 2 3 4 5 6 7");
|
||||
//Console.WriteLine("01234567890123456789012345678901234567890123456789012345678901234567890123456789");
|
||||
@@ -161,7 +163,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
// generate an array of "--" as header markers below
|
||||
// the column header labels
|
||||
string[] breakLine = new string[values.Length];
|
||||
for (int k = 0; k < _si.columnInfo.Length; k++)
|
||||
for (int k = 0; k < breakLine.Length; k++)
|
||||
{
|
||||
// the column can be hidden
|
||||
if (_si.columnInfo[k].width <= 0)
|
||||
@@ -185,25 +187,25 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
GenerateRow(breakLine, lo, false, null, lo.DisplayCells);
|
||||
}
|
||||
|
||||
internal void GenerateRow(string[] values, LineOutput lo, bool multiLine, int[] alignment, DisplayCells dc)
|
||||
internal void GenerateRow(string[] values, LineOutput lo, bool multiLine, ReadOnlySpan<int> alignment, DisplayCells dc)
|
||||
{
|
||||
if (_disabled)
|
||||
return;
|
||||
|
||||
// build the current row alignment settings
|
||||
int cols = _si.columnInfo.Length;
|
||||
int[] currentAlignment = new int[cols];
|
||||
Span<int> currentAlignment = stackalloc int[cols];
|
||||
|
||||
if (alignment == null)
|
||||
{
|
||||
for (int i = 0; i < cols; i++)
|
||||
for (int i = 0; i < currentAlignment.Length; i++)
|
||||
{
|
||||
currentAlignment[i] = _si.columnInfo[i].alignment;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < cols; i++)
|
||||
for (int i = 0; i < currentAlignment.Length; i++)
|
||||
{
|
||||
if (alignment[i] == TextAlignment.Undefined)
|
||||
currentAlignment[i] = _si.columnInfo[i].alignment;
|
||||
@@ -227,10 +229,10 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
}
|
||||
}
|
||||
|
||||
private string[] GenerateTableRow(string[] values, int[] alignment, DisplayCells ds)
|
||||
private string[] GenerateTableRow(string[] values, ReadOnlySpan<int> alignment, DisplayCells ds)
|
||||
{
|
||||
// select the active columns (skip hidden ones)
|
||||
int[] validColumnArray = new int[_si.columnInfo.Length];
|
||||
Span<int> validColumnArray = stackalloc int[_si.columnInfo.Length];
|
||||
int validColumnCount = 0;
|
||||
for (int k = 0; k < _si.columnInfo.Length; k++)
|
||||
{
|
||||
@@ -241,7 +243,9 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
}
|
||||
|
||||
if (validColumnCount == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
StringCollection[] scArray = new StringCollection[validColumnCount];
|
||||
bool addPadding = true;
|
||||
@@ -353,7 +357,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
|
||||
// finally, build an array of strings
|
||||
string[] rows = new string[screenRows];
|
||||
for (int row = 0; row < rows.Length; row++)
|
||||
for (int row = 0; row < screenRows; row++)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// for a given row, walk the columns
|
||||
@@ -371,6 +375,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
}
|
||||
rows[row] = sb.ToString();
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
@@ -390,7 +395,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
return sc;
|
||||
}
|
||||
|
||||
private string GenerateRow(string[] values, int[] alignment, DisplayCells dc)
|
||||
private string GenerateRow(string[] values, ReadOnlySpan<int> alignment, DisplayCells dc)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -408,7 +413,6 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
// skip columns that are not at least a single character wide
|
||||
continue;
|
||||
}
|
||||
int newRowIndex = sb.Length;
|
||||
|
||||
// NOTE: the following padding operations assume that we
|
||||
// pad with a blank (or any character that ALWAYS maps to a single screen cell
|
||||
@@ -432,7 +436,7 @@ namespace Microsoft.PowerShell.Commands.Internal.Format
|
||||
private static string GenerateRowField(string val, int width, int alignment, DisplayCells dc, bool addPadding)
|
||||
{
|
||||
// make sure the string does not have any embedded <CR> in it
|
||||
string s = StringManipulationHelper.TruncateAtNewLine(val) ?? "";
|
||||
string s = StringManipulationHelper.TruncateAtNewLine(val);
|
||||
|
||||
string currentValue = s;
|
||||
int currentValueDisplayLength = dc.Length(currentValue);
|
||||
|
||||
Reference in New Issue
Block a user