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

Replace confusing new T[] { ... } optimization with collection expressions #93125

Merged
merged 3 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,8 @@ internal CorElementType CorElementType
{
get
{
ReadOnlySpan<byte> map = new byte[]
{
ReadOnlySpan<byte> map =
[
default,
(byte)CorElementType.ELEMENT_TYPE_VOID, // EETypeElementType.Void
(byte)CorElementType.ELEMENT_TYPE_BOOLEAN, // EETypeElementType.Boolean
Expand Down Expand Up @@ -377,7 +377,7 @@ internal CorElementType CorElementType
default,
default,
default
};
];

// Verify last element of the map
Debug.Assert((byte)CorElementType.ELEMENT_TYPE_FNPTR == map[(int)EETypeElementType.FunctionPointer]);
Expand Down
6 changes: 3 additions & 3 deletions src/libraries/Common/src/System/HexConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ public static bool IsHexLowerChar(int c)
}

/// <summary>Map from an ASCII char to its hex value, e.g. arr['b'] == 11. 0xFF means it's not a hex digit.</summary>
public static ReadOnlySpan<byte> CharToHexLookup => new byte[]
{
public static ReadOnlySpan<byte> CharToHexLookup =>
[
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 15
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 31
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 47
Expand All @@ -440,6 +440,6 @@ public static bool IsHexLowerChar(int c)
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 223
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 239
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 255
};
];
}
}
5 changes: 3 additions & 2 deletions src/libraries/Common/src/System/Net/CaseInsensitiveAscii.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ internal sealed class CaseInsensitiveAscii : IEqualityComparer, IComparer
{
// ASCII char ToLower table
internal static readonly CaseInsensitiveAscii StaticInstance = new CaseInsensitiveAscii();
internal static ReadOnlySpan<byte> AsciiToLower => new byte[] {
internal static ReadOnlySpan<byte> AsciiToLower =>
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
Expand All @@ -38,7 +39,7 @@ internal sealed class CaseInsensitiveAscii : IEqualityComparer, IComparer
230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
250, 251, 252, 253, 254, 255
};
];

// ASCII string case insensitive hash function
public int GetHashCode(object myObject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ internal static class Huffman
{
// HPack static huffman code. see: https://httpwg.org/specs/rfc7541.html#huffman.code
// Stored into two tables to optimize its initialization and memory consumption.
private static ReadOnlySpan<uint> EncodingTableCodes => new uint[257]
{
private static ReadOnlySpan<uint> EncodingTableCodes => // 257
[
0b11111111_11000000_00000000_00000000,
0b11111111_11111111_10110000_00000000,
0b11111111_11111111_11111110_00100000,
Expand Down Expand Up @@ -270,10 +270,10 @@ internal static class Huffman
0b11111111_11111111_11111110_00000000,
0b11111111_11111111_11111011_10000000,
0b11111111_11111111_11111111_11111100,
};
];

private static ReadOnlySpan<byte> EncodingTableBitLengths => new byte[257]
{
private static ReadOnlySpan<byte> EncodingTableBitLengths => // 257
[
13,
23,
28,
Expand Down Expand Up @@ -531,7 +531,7 @@ internal static class Huffman
27,
26,
30
};
];

private static readonly ushort[] s_decodingTree = GenerateDecodingLookupTree();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ namespace System.Security.Cryptography.Asn1
[StructLayout(LayoutKind.Sequential)]
internal partial struct OaepParamsAsn
{
private static ReadOnlySpan<byte> DefaultHashFunc => new byte[] { 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00 };
private static ReadOnlySpan<byte> DefaultHashFunc => [0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00];
stephentoub marked this conversation as resolved.
Show resolved Hide resolved
stephentoub marked this conversation as resolved.
Show resolved Hide resolved

private static ReadOnlySpan<byte> DefaultMaskGenFunc => new byte[] { 0x30, 0x16, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00 };
private static ReadOnlySpan<byte> DefaultMaskGenFunc => [0x30, 0x16, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00];

private static ReadOnlySpan<byte> DefaultPSourceFunc => new byte[] { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x09, 0x04, 0x00 };
private static ReadOnlySpan<byte> DefaultPSourceFunc => [0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x09, 0x04, 0x00];

internal System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn HashFunc;
internal System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn MaskGenFunc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace System.Security.Cryptography.Asn1
[StructLayout(LayoutKind.Sequential)]
internal partial struct Pbkdf2Params
{
private static ReadOnlySpan<byte> DefaultPrf => new byte[] { 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x07, 0x05, 0x00 };
private static ReadOnlySpan<byte> DefaultPrf => [0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x07, 0x05, 0x00];

internal System.Security.Cryptography.Asn1.Pbkdf2SaltChoice Salt;
internal int IterationCount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace System.Security.Cryptography.Asn1.Pkcs12
[StructLayout(LayoutKind.Sequential)]
internal partial struct MacData
{
private static ReadOnlySpan<byte> DefaultIterationCount => new byte[] { 0x02, 0x01, 0x01 };
private static ReadOnlySpan<byte> DefaultIterationCount => [0x02, 0x01, 0x01];

internal System.Security.Cryptography.Asn1.DigestInfoAsn Mac;
internal ReadOnlyMemory<byte> MacSalt;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ namespace System.Security.Cryptography.Asn1
[StructLayout(LayoutKind.Sequential)]
internal partial struct PssParamsAsn
{
private static ReadOnlySpan<byte> DefaultHashAlgorithm => new byte[] { 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00 };
private static ReadOnlySpan<byte> DefaultHashAlgorithm => [0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00];

private static ReadOnlySpan<byte> DefaultMaskGenAlgorithm => new byte[] { 0x30, 0x16, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00 };
private static ReadOnlySpan<byte> DefaultMaskGenAlgorithm => [0x30, 0x16, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00];

private static ReadOnlySpan<byte> DefaultSaltLength => new byte[] { 0x02, 0x01, 0x14 };
private static ReadOnlySpan<byte> DefaultSaltLength => [0x02, 0x01, 0x14];

private static ReadOnlySpan<byte> DefaultTrailerField => new byte[] { 0x02, 0x01, 0x01 };
private static ReadOnlySpan<byte> DefaultTrailerField => [0x02, 0x01, 0x01];

internal System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn HashAlgorithm;
internal System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn MaskGenAlgorithm;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ namespace System.Security.Cryptography.Asn1
// smallest supported by .NET that's not really a problem.
internal partial struct Rc2CbcParameters
{
private static ReadOnlySpan<byte> Rc2EkbEncoding => new byte[]
{
private static ReadOnlySpan<byte> Rc2EkbEncoding =>
[
0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0,
0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a,
0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36,
Expand All @@ -30,7 +30,7 @@ internal partial struct Rc2CbcParameters
0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5,
0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,
0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab,
};
];

internal Rc2CbcParameters(ReadOnlyMemory<byte> iv, int keySize)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace System.Security.Cryptography.Asn1
[StructLayout(LayoutKind.Sequential)]
internal partial struct X509ExtensionAsn
{
private static ReadOnlySpan<byte> DefaultCritical => new byte[] { 0x01, 0x01, 0x00 };
private static ReadOnlySpan<byte> DefaultCritical => [0x01, 0x01, 0x00];

internal string ExtnId;
internal bool Critical;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ namespace <xsl:value-of select="@namespace" />
</xsl:template>

<xsl:template match="*[@defaultDerInit]" mode="DefaultFieldDef">
private static ReadOnlySpan&lt;byte&gt; <xsl:call-template name="DefaultValueField"/> =&gt; new byte[] { <xsl:value-of select="@defaultDerInit"/> };
private static ReadOnlySpan&lt;byte&gt; <xsl:call-template name="DefaultValueField"/> =&gt; [<xsl:value-of select="@defaultDerInit"/>];
</xsl:template>

<xsl:template match="*[@defaultDerInit]" mode="DefaultFieldVerify">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,62 +10,62 @@ namespace System.Security.Cryptography
internal static class RsaPaddingProcessor
{
// DigestInfo header values taken from https://tools.ietf.org/html/rfc3447#section-9.2, Note 1.
private static ReadOnlySpan<byte> DigestInfoMD5 => new byte[]
{
private static ReadOnlySpan<byte> DigestInfoMD5 =>
[
0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86,
0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00,
0x04, 0x10,
};
];

private static ReadOnlySpan<byte> DigestInfoSha1 => new byte[]
{
private static ReadOnlySpan<byte> DigestInfoSha1 =>
[
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03,
0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,
};
];

private static ReadOnlySpan<byte> DigestInfoSha256 => new byte[]
{
private static ReadOnlySpan<byte> DigestInfoSha256 =>
[
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
0x20,
};
];

private static ReadOnlySpan<byte> DigestInfoSha384 => new byte[]
{
private static ReadOnlySpan<byte> DigestInfoSha384 =>
[
0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04,
0x30,
};
];

private static ReadOnlySpan<byte> DigestInfoSha512 => new byte[]
{
private static ReadOnlySpan<byte> DigestInfoSha512 =>
[
0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04,
0x40,
};
];

private static ReadOnlySpan<byte> DigestInfoSha3_256 => new byte[]
{
private static ReadOnlySpan<byte> DigestInfoSha3_256 =>
[
0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04,
0x20,
};
];

private static ReadOnlySpan<byte> DigestInfoSha3_384 => new byte[]
{
private static ReadOnlySpan<byte> DigestInfoSha3_384 =>
[
0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04,
0x30,
};
];

private static ReadOnlySpan<byte> DigestInfoSha3_512 => new byte[]
{
private static ReadOnlySpan<byte> DigestInfoSha3_512 =>
[
0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
0x01, 0x65, 0x03, 0x04, 0x02, 0x0A, 0x05, 0x00, 0x04,
0x40,
};
];

private static ReadOnlySpan<byte> EightZeros => new byte[8];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this one was actually allocating on each call :(

Copy link
Member

@danmoseley danmoseley Oct 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that necessarily bad? Often we avoid caching memory that would never leave Gen0 (I don't know this code OC)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that necessarily bad? Often we avoid caching memory that would never leave Gen0 (I don't know this code OC)

If this had instead been:

private static ReadOnlySpan<byte> EightZeros => new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 };

there wouldn't have been any allocation, not even on first use: it would have simply been eight zero'd bytes in the assembly data, and the span would have pointed directly to that memory.
SharpLab

And, yes, a property that looks like it should be non-allocating but that allocates on every access is bad :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, wow, TIL.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should just fix that in Roslyn. I don't see a good reason for these two to exhibit such a codegen difference. (Though moving forward we'll use that syntax much less and so hopefully won't trip over it again.)
cc: @jcouv

private static ReadOnlySpan<byte> EightZeros => [0, 0, 0, 0, 0, 0, 0, 0];

private static ReadOnlySpan<byte> GetDigestInfoForAlgorithm(
HashAlgorithmName hashAlgorithmName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Microsoft.Extensions.DependencyModel
public class DependencyContextJsonReader : IDependencyContextReader
{
private const int UnseekableStreamInitialRentSize = 4096;
private static ReadOnlySpan<byte> Utf8Bom => new byte[] { 0xEF, 0xBB, 0xBF };
private static ReadOnlySpan<byte> Utf8Bom => [0xEF, 0xBB, 0xBF];

private readonly Dictionary<string, string> _stringPool = new Dictionary<string, string>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ internal sealed class XmlUtil : IDisposable, IConfigErrorInfo

// Offset from where the reader reports the LinePosition of an Xml Node to
// the start of that representation in text.
private static ReadOnlySpan<int> PositionOffset => new int[]
{
private static ReadOnlySpan<int> PositionOffset =>
[
0, // None,
1, // Element, <elem
-1, // Attribute, N/A
Expand All @@ -46,7 +46,7 @@ internal sealed class XmlUtil : IDisposable, IConfigErrorInfo
2, // EndElement, />
-1, // EndEntity, N/A
2, // XmlDeclaration <?xml
};
];

private StringWriter _cachedStringWriter;
private int _lastLineNumber;
Expand Down
6 changes: 3 additions & 3 deletions src/libraries/System.Console/src/System/ConsolePal.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,8 @@ private static void WriteSetColorString(bool foreground, ConsoleColor color)
// The values of the ConsoleColor enums unfortunately don't map to the
// corresponding ANSI values. We need to do the mapping manually.
// See http://en.wikipedia.org/wiki/ANSI_escape_code#Colors
ReadOnlySpan<byte> consoleColorToAnsiCode = new byte[] // rely on C# compiler optimization to avoid array allocation
{
ReadOnlySpan<byte> consoleColorToAnsiCode =
[
// Dark/Normal colors
0, // Black,
4, // DarkBlue,
Expand All @@ -837,7 +837,7 @@ private static void WriteSetColorString(bool foreground, ConsoleColor color)
13, // Magenta,
11, // Yellow,
15 // White
};
];

int ansiCode = consoleColorToAnsiCode[ccValue] % maxColors;
evaluatedString = TermInfo.ParameterizedStrings.Evaluate(formatString, ansiCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ internal static bool IsRelational(int op)
/// <summary>Mapping from Operator to priorities.</summary>
internal static int Priority(int op)
{
ReadOnlySpan<byte> priorities = new byte[]
{
ReadOnlySpan<byte> priorities =
[
PriStart, // Noop
PriNeg, PriNeg, PriNot, // Unary -, +, Not
PriBetweenAnd, PriBetweenInLike, PriBetweenInLike,
Expand All @@ -137,7 +137,7 @@ internal static int Priority(int op)
PriParen, PriProc, PriDot, PriDot, // Proc, Iff, Qula, Dot..

// anything beyond is PriMax
};
];

return (uint)op < (uint)priorities.Length ? priorities[op] : PriMax;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ public struct SqlDateTime : INullable, IComparable, IXmlSerializable, IEquatable

private const int s_dayBase = 693595; // Jan 1 1900 is this many days from Jan 1 0001

private static ReadOnlySpan<int> DaysToMonth365 => new int[] {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
private static ReadOnlySpan<int> DaysToMonth366 => new int[] {
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
private static ReadOnlySpan<int> DaysToMonth365 => [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
private static ReadOnlySpan<int> DaysToMonth366 => [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366];

private static readonly TimeSpan s_minTimeSpan = new DateTime(1753, 1, 1).Subtract(s_SQLBaseDate);
private static readonly TimeSpan s_maxTimeSpan = DateTime.MaxValue.Subtract(s_SQLBaseDate);
Expand Down
Loading
Loading