当我查看反编译的 .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 内存开销相当小的实例。

有帮助吗?

解决方案

它是每线程缓存,因此预计数量较低。最好使用 参考来源 对于这样的问题,您也会看到评论。看起来像(编辑以适合):

    // 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 设计师”有点令人费解。好吧,其实并不是,这项工作肯定是为了优化 Visual Studio 而完成的。如果 Neelie Kroes 发现的话,她将会大放异彩,欧盟还将获得另外 10 亿美元:)

其他提示

大多数构建的字符串可能都很小,因此使用相对较小的缓冲区大小将覆盖大部分操作,同时不会占用太多内存。考虑有一个线程池,可能创建了许多线程。如果它们中的每一个都占用 2kB 的缓存缓冲区,那么它就会增加一定量的内存。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top