Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit b3005fe

Browse files
justinvpjkotas
authored andcommitted
Reduce allocations in StringBuilder.AppendFormat for primitive types (#15110)
Use the new `TryFormat` APIs to avoid string allocations for primitive types inside `StringBuilder.AppendFormat`, used by `string.Format`/interpolated strings.
1 parent 8058720 commit b3005fe

File tree

16 files changed

+54
-16
lines changed

16 files changed

+54
-16
lines changed

src/mscorlib/shared/System.Private.CoreLib.Shared.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@
211211
<Compile Include="$(MSBuildThisFileDirectory)System\IObservable.cs" />
212212
<Compile Include="$(MSBuildThisFileDirectory)System\IObserver.cs" />
213213
<Compile Include="$(MSBuildThisFileDirectory)System\IProgress.cs" />
214+
<Compile Include="$(MSBuildThisFileDirectory)System\ISpanFormattable.cs" />
214215
<Compile Include="$(MSBuildThisFileDirectory)System\Int16.cs" />
215216
<Compile Include="$(MSBuildThisFileDirectory)System\Int32.cs" />
216217
<Compile Include="$(MSBuildThisFileDirectory)System\Int64.cs" />

src/mscorlib/shared/System/Byte.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace System
1212
[Serializable]
1313
[StructLayout(LayoutKind.Sequential)]
1414
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
15-
public struct Byte : IComparable, IConvertible, IFormattable, IComparable<Byte>, IEquatable<Byte>
15+
public struct Byte : IComparable, IConvertible, IFormattable, IComparable<Byte>, IEquatable<Byte>, ISpanFormattable
1616
{
1717
private byte m_value; // Do not rename (binary serialization)
1818

src/mscorlib/shared/System/DateTime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace System
5353
[StructLayout(LayoutKind.Auto)]
5454
[Serializable]
5555
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
56-
public readonly partial struct DateTime : IComparable, IFormattable, IConvertible, IComparable<DateTime>, IEquatable<DateTime>, ISerializable
56+
public readonly partial struct DateTime : IComparable, IFormattable, IConvertible, IComparable<DateTime>, IEquatable<DateTime>, ISerializable, ISpanFormattable
5757
{
5858
// Number of 100ns ticks per time unit
5959
private const long TicksPerMillisecond = 10000;

src/mscorlib/shared/System/DateTimeOffset.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace System
3131
[StructLayout(LayoutKind.Auto)]
3232
[Serializable]
3333
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
34-
public struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback
34+
public struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback, ISpanFormattable
3535
{
3636
// Constants
3737
internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14;

src/mscorlib/shared/System/Guid.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace System
1313
[Serializable]
1414
[Runtime.Versioning.NonVersionable] // This only applies to field layout
1515
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
16-
public partial struct Guid : IFormattable, IComparable, IComparable<Guid>, IEquatable<Guid>
16+
public partial struct Guid : IFormattable, IComparable, IComparable<Guid>, IEquatable<Guid>, ISpanFormattable
1717
{
1818
public static readonly Guid Empty = new Guid();
1919

@@ -1426,5 +1426,11 @@ public bool TryFormat(Span<char> destination, out int charsWritten, string forma
14261426
charsWritten = guidSize;
14271427
return true;
14281428
}
1429+
1430+
bool ISpanFormattable.TryFormat(Span<char> destination, out int charsWritten, string format, IFormatProvider provider)
1431+
{
1432+
// Like with the IFormattable implementation, provider is ignored.
1433+
return TryFormat(destination, out charsWritten, format);
1434+
}
14291435
}
14301436
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace System
6+
{
7+
internal interface ISpanFormattable
8+
{
9+
bool TryFormat(Span<char> destination, out int charsWritten, string format = null, IFormatProvider provider = null);
10+
}
11+
}

src/mscorlib/shared/System/Int16.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace System
1212
[Serializable]
1313
[StructLayout(LayoutKind.Sequential)]
1414
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
15-
public struct Int16 : IComparable, IConvertible, IFormattable, IComparable<Int16>, IEquatable<Int16>
15+
public struct Int16 : IComparable, IConvertible, IFormattable, IComparable<Int16>, IEquatable<Int16>, ISpanFormattable
1616
{
1717
private short m_value; // Do not rename (binary serialization)
1818

src/mscorlib/shared/System/Int32.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace System
1212
[Serializable]
1313
[StructLayout(LayoutKind.Sequential)]
1414
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
15-
public struct Int32 : IComparable, IConvertible, IFormattable, IComparable<Int32>, IEquatable<Int32>
15+
public struct Int32 : IComparable, IConvertible, IFormattable, IComparable<Int32>, IEquatable<Int32>, ISpanFormattable
1616
{
1717
private int m_value; // Do not rename (binary serialization)
1818

src/mscorlib/shared/System/Int64.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace System
1212
[Serializable]
1313
[StructLayout(LayoutKind.Sequential)]
1414
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
15-
public struct Int64 : IComparable, IConvertible, IFormattable, IComparable<Int64>, IEquatable<Int64>
15+
public struct Int64 : IComparable, IConvertible, IFormattable, IComparable<Int64>, IEquatable<Int64>, ISpanFormattable
1616
{
1717
private long m_value; // Do not rename (binary serialization)
1818

src/mscorlib/shared/System/SByte.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace System
1212
[Serializable]
1313
[CLSCompliant(false)] [StructLayout(LayoutKind.Sequential)]
1414
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
15-
public struct SByte : IComparable, IConvertible, IFormattable, IComparable<SByte>, IEquatable<SByte>
15+
public struct SByte : IComparable, IConvertible, IFormattable, IComparable<SByte>, IEquatable<SByte>, ISpanFormattable
1616
{
1717
private sbyte m_value; // Do not rename (binary serialization)
1818

0 commit comments

Comments
 (0)