.NET内部StringBuilderCache类配置的理解

13

当我查看反编译的 .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`实例从而减少内存开销。

虽然这个缓存模式非常聪明,我一定会记住。但是我想知道为什么MAX_BUILDER_SIZE如此之小?将它设置为2KB是否更好?这将可以防止创建较大的StringBuilder实例从而减少内存开销。


2
看起来在 corefx 项目中,这个大小现在更低了(MAX_BUILDER_SIZE = 260)https://github.com/dotnet/corefx/blob/master/src/Common/src/System/IO/StringBuilderCache.cs - Romain Hautefeuille
2个回答

18

这是一个每个线程都有自己缓存的机制,因此较低的数字是预期的。最好使用参考源代码来了解此类问题,您将看到注释,就像这样(进行了编辑以适应):

    // 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;

"VS designers"有点令人困惑。但实际上,这项工作肯定是为了优化Visual Studio而完成的。如果Neelie Kroes发现了这件事,欧盟又会多出十亿美元 :)


6

大多数构建的字符串可能都是小型的,因此使用相对较小的缓冲区大小将涵盖大多数操作,同时不会占用太多内存。考虑到可能创建许多线程的线程池,如果每个线程都使用2kB的缓存缓冲区,那么这将增加一定量的内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接