当我查看反编译的.NET程序集以查看一些内部结构时,我注意到了多个框架方法使用的有趣的StringBuilderCache
类:
internal static class StringBuilderCache
{
[ThreadStatic]
private static StringBuilder CachedInstance;
private const int MAX_BUILDER_SIZE = 360;
public static StringBuilder Acquire(int capacity = 16)
{
if (capacity <= 360)
{
StringBuilder cachedInstance = StringBuilderCache.CachedInstance;
if (cachedInstance != null && capacity <= cachedInstance.Capacity)
{
StringBuilderCache.CachedInstance = null;
cachedInstance.Clear();
return cachedInstance;
}
}
return new StringBuilder(capacity);
}
public static void Release(StringBuilder sb)
{
if (sb.Capacity <= 360)
{
StringBuilderCache.CachedInstance = sb;
}
}
public static string GetStringAndRelease(StringBuilder sb)
{
string result = sb.ToString();
StringBuilderCache.Release(sb);
return result;
}
}
我们可以在string.Format
方法中找到示例用法:
public static string Format(IFormatProvider provider, string format, params object[] args)
{
...
StringBuilder stringBuilder = StringBuilderCache.Acquire(format.Length + args.Length * 8);
stringBuilder.AppendFormat(provider, format, args);
return StringBuilderCache.GetStringAndRelease(stringBuilder);
}
虽然它非常聪明并且肯定会记住这种缓存模式,但我想知道为什么MAX_BUILDER_SIZE
如此之小?将它设置为,设置2kB,会不会更好?它可以防止在内存开销很小的情况下创建更大的StringBuilder
实例。
答案 0 :(得分:17)
这是一个每线程缓存,因此预计数量较少。最好使用Reference Source这样的问题,你也会看到评论。看起来像(编辑适合):
// The value 360 was chosen in discussion with performance experts as a
// compromise between using as litle memory (per thread) as possible and
// still covering a large part of short-lived StringBuilder creations on
// the startup path of VS designers.
private const int MAX_BUILDER_SIZE = 360;
答案 1 :(得分:5)
大多数构建的字符串可能很小,因此使用相对较小的缓冲区大小将覆盖大部分操作,同时不会消耗太多内存。考虑到有一个线程池可能创建了许多线程。如果它们中的每一个都需要高达2kB的缓存缓冲区,它会增加一些内存。