diff options
author | Stephen Toub <stoub@microsoft.com> | 2019-01-21 16:20:18 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-21 16:20:18 -0500 |
commit | 401e931714e9b0890aaaa047710d0eb582bb8722 (patch) | |
tree | aaa793feae354a85a4d3a707188f4e872e5726be /src | |
parent | a5c5feb8939ae6ae10d9d2b7f2bc8d43ed99bc38 (diff) | |
download | coreclr-401e931714e9b0890aaaa047710d0eb582bb8722.tar.gz coreclr-401e931714e9b0890aaaa047710d0eb582bb8722.tar.bz2 coreclr-401e931714e9b0890aaaa047710d0eb582bb8722.zip |
Avoid intermediate strings in some StringBuilder formatting (#22111)
* Avoid intermediate strings in some StringBuilder formatting
Several appends to string builders are first creating strings and then appending those strings, and they're not using the existing Append(primitive) overloads because they want to customize the format string or provider as part of appending the value. This fixes a few of those cases, using another internal AppendSpanFormattable overload on StringBuilder.
* Address PR feedback
Diffstat (limited to 'src')
4 files changed, 30 insertions, 16 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs index 61143fecfd..b105324a6b 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs @@ -509,7 +509,7 @@ namespace System fraction = fraction / (long)Math.Pow(10, 7 - tokenLen); if (ch == 'f') { - result.Append(((int)fraction).ToString(fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture)); + result.AppendSpanFormattable((int)fraction, fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture); } else { @@ -528,7 +528,7 @@ namespace System } if (effectiveDigits > 0) { - result.Append(((int)fraction).ToString(fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture)); + result.AppendSpanFormattable((int)fraction, fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture); } else { @@ -679,10 +679,13 @@ namespace System { FormatDigits(result, year % 100, tokenLen); } + else if (tokenLen <= 16) // FormatDigits has an implicit 16-digit limit + { + FormatDigits(result, year, tokenLen, overrideLengthLimit: true); + } else { - string fmtPattern = "D" + tokenLen.ToString(); - result.Append(year.ToString(fmtPattern, CultureInfo.InvariantCulture)); + result.Append(year.ToString("D" + tokenLen.ToString(), CultureInfo.InvariantCulture)); } } bTimeOnly = false; diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs index 5e553d56b4..ccb42ad87c 100644 --- a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs +++ b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs @@ -400,7 +400,7 @@ namespace System.Globalization tmp = fraction; tmp /= TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - tokenLen); - result.Append((tmp).ToString(DateTimeFormat.fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture)); + result.AppendSpanFormattable(tmp, DateTimeFormat.fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture); break; case 'F': // @@ -429,7 +429,7 @@ namespace System.Globalization } if (effectiveDigits > 0) { - result.Append((tmp).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture)); + result.AppendSpanFormattable(tmp, DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture); } break; case 'd': diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs index 75b7ed6b4a..cd88d2199d 100644 --- a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs @@ -1179,6 +1179,17 @@ namespace System.Text return Append(value.ToString()); } + internal StringBuilder AppendSpanFormattable<T>(T value, string format, IFormatProvider provider) where T : ISpanFormattable, IFormattable + { + if (value.TryFormat(RemainingCurrentChunk, out int charsWritten, format, provider)) + { + m_ChunkLength += charsWritten; + return this; + } + + return Append(value.ToString(format, provider)); + } + public StringBuilder Append(object value) => (value == null) ? this : Append(value.ToString()); public StringBuilder Append(char[] value) diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.StringSerializer.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.StringSerializer.cs index e3e9ddbf58..a0b92eaac9 100644 --- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.StringSerializer.cs +++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.StringSerializer.cs @@ -49,7 +49,7 @@ namespace System // SerializeSubstitute(zone.Id, serializedText); serializedText.Append(Sep); - serializedText.Append(zone.BaseUtcOffset.TotalMinutes.ToString(CultureInfo.InvariantCulture)); + serializedText.AppendSpanFormattable(zone.BaseUtcOffset.TotalMinutes, format: default, CultureInfo.InvariantCulture); serializedText.Append(Sep); SerializeSubstitute(zone.DisplayName, serializedText); serializedText.Append(Sep); @@ -62,11 +62,11 @@ namespace System foreach (AdjustmentRule rule in rules) { serializedText.Append(Lhs); - serializedText.Append(rule.DateStart.ToString(DateTimeFormat, DateTimeFormatInfo.InvariantInfo)); + serializedText.AppendSpanFormattable(rule.DateStart, DateTimeFormat, DateTimeFormatInfo.InvariantInfo); serializedText.Append(Sep); - serializedText.Append(rule.DateEnd.ToString(DateTimeFormat, DateTimeFormatInfo.InvariantInfo)); + serializedText.AppendSpanFormattable(rule.DateEnd, DateTimeFormat, DateTimeFormatInfo.InvariantInfo); serializedText.Append(Sep); - serializedText.Append(rule.DaylightDelta.TotalMinutes.ToString(CultureInfo.InvariantCulture)); + serializedText.AppendSpanFormattable(rule.DaylightDelta.TotalMinutes, format: default, CultureInfo.InvariantCulture); serializedText.Append(Sep); // serialize the TransitionTime's SerializeTransitionTime(rule.DaylightTransitionStart, serializedText); @@ -76,7 +76,7 @@ namespace System if (rule.BaseUtcOffsetDelta != TimeSpan.Zero) { // Serialize it only when BaseUtcOffsetDelta has a value to reduce the impact of adding rule.BaseUtcOffsetDelta - serializedText.Append(rule.BaseUtcOffsetDelta.TotalMinutes.ToString(CultureInfo.InvariantCulture)); + serializedText.AppendSpanFormattable(rule.BaseUtcOffsetDelta.TotalMinutes, format: default, CultureInfo.InvariantCulture); serializedText.Append(Sep); } if (rule.NoDaylightTransitions) @@ -155,20 +155,20 @@ namespace System serializedText.Append(Lhs); serializedText.Append(time.IsFixedDateRule ? '1' : '0'); serializedText.Append(Sep); - serializedText.Append(time.TimeOfDay.ToString(TimeOfDayFormat, DateTimeFormatInfo.InvariantInfo)); + serializedText.AppendSpanFormattable(time.TimeOfDay, TimeOfDayFormat, DateTimeFormatInfo.InvariantInfo); serializedText.Append(Sep); - serializedText.Append(time.Month.ToString(CultureInfo.InvariantCulture)); + serializedText.AppendSpanFormattable(time.Month, format: default, CultureInfo.InvariantCulture); serializedText.Append(Sep); if (time.IsFixedDateRule) { - serializedText.Append(time.Day.ToString(CultureInfo.InvariantCulture)); + serializedText.AppendSpanFormattable(time.Day, format: default, CultureInfo.InvariantCulture); serializedText.Append(Sep); } else { - serializedText.Append(time.Week.ToString(CultureInfo.InvariantCulture)); + serializedText.AppendSpanFormattable(time.Week, format: default, CultureInfo.InvariantCulture); serializedText.Append(Sep); - serializedText.Append(((int)time.DayOfWeek).ToString(CultureInfo.InvariantCulture)); + serializedText.AppendSpanFormattable((int)time.DayOfWeek, format: default, CultureInfo.InvariantCulture); serializedText.Append(Sep); } serializedText.Append(Rhs); |