tgoop.com/csharp_gepard/88
Last Update:
Дата и StringBuilder #память #бенч
При работе со StringBuilder
есть ещё одна неприятность: метод StringBuilder.Append
прекрасен, но, по какой-то странной для меня причине, не имеет перегрузки для DateTime. Я знаю, что многие разработчики просто передают туда дату и... попадают на boxing, поскольку будет выбран метод с сигнатурой, принимающей object
. Либо, что тоже странно, коллеги просто делают dateTime.ToString()
, аллоцируя промежуточную строку и просто передавая её в StringBuilder.Append.
Вроде бы ничего страшного, вроде бы очень очень маленькая аллокация. Но на больших объемах GC будет чаще собирать мусор, чаще нагружать процессор, а значит будет оставаться меньше процессорного времени для бизнесовых задач. Не надо так.
Победить это просто. Мы уже знаем про метод AppendSpanFormattable
из реализации ValueStringBuilder
, который принимает значения, реализующие ISpanFormattable
. Следовательно, нам нужно просто создать метод-расширение для StringBuilder'a с почти таким же кодом:
public static StringBuilder AppendSpanFormattable<T>(
this StringBuilder sb,
T value, string format, int bufferSize = 64) where T: ISpanFormattable
{
Span<char> buffer = stackalloc char[bufferSize];
if (value.TryFormat(buffer, out var written, format, null)) {
sb.Append(buffer[..written]);
}
else {
sb.Append(value);
}
return sb;
}
Результаты улучшения на скриншоте. Обратите внимание, что аллокация пропала и результат очень похож на результаты с ValueStringBuilder.
Код бенчмарка в комментариях.
P.S.: Если вы сразу хотите перейти к правильному варианту, минуя ValueStringBuilder'ы и прочие ухищрения - см. вот этот коммент. Другой вопрос, что без понимания КАК это работает, будет сложно это заиспользовать - выглядит как натуральная магия.
BY C# Heppard

Share with your friend now:
tgoop.com/csharp_gepard/88