问题描述
当我查看反编译的.NET程序集以了解一些内部信息时,我注意到多个框架方法使用的有趣的 StringBuilderCache
类:
内部静态类StringBuilderCache{[ThreadStatic]私有静态StringBuilder CachedInstance;私有const int MAX_BUILDER_SIZE = 360;公共静态StringBuilder Acquire(int容量= 16){如果(容量< = 360){StringBuilder cachedInstance = StringBuilderCache.CachedInstance;if(cachedInstance!=空&&容量< = cachedInstance.Capacity){StringBuilderCache.CachedInstance = null;cachedInstance.Clear();返回cachedInstance;}}返回新的StringBuilder(capacity);}公共静态无效Release(StringBuilder sb){如果(sb.Capacity< = 360){StringBuilderCache.CachedInstance = sb;}}公共静态字符串GetStringAndRelease(StringBuilder sb){字符串结果= sb.ToString();StringBuilderCache.Release(sb);返回结果;}}
示例用法,例如,我们可以在 string.Format
方法中找到
公共静态字符串Format(IFormatProvider提供程序,字符串格式,params对象[] args){...StringBuilder stringBuilder = StringBuilderCache.Acquire(format.Length + args.Length * 8);stringBuilder.AppendFormat(provider,format,args);返回StringBuilderCache.GetStringAndRelease(stringBuilder);}
虽然非常聪明,并且可以肯定我会记得这种缓存模式,但我想知道为什么 MAX_BUILDER_SIZE
这么小?将其设置为2kB,会更好吗?这样可以避免以较小的内存开销创建更大的 StringBuilder
实例.
这是一个基于线程的缓存,因此数量较少.最好将参考源用于此类问题,您也将看到注释,其中看起来像(已编辑为适合):
//值360是在与性能专家讨论时选择的//尽量减少使用litle内存(每个线程)和//仍然涵盖了短暂的StringBuilder创建的大部分内容//VS设计器的启动路径.私有const int MAX_BUILDER_SIZE = 360;
"VS设计师"有点令人费解.好吧,不是真的,可以肯定的是,这项工作是为了优化Visual Studio而完成的.妮莉·克罗斯(Neelie Kroes)将会在野外度过一天,如果她能找到的话,欧盟将再有10亿美元:
When I was looking at decompiled .NET assemblies to see some internals, I've noticed interesting StringBuilderCache
class used by multiple framework's methods:
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;
}
}
Example usage we can find for example in string.Format
method:
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);
}
While it is quite clever and for sure I will remember about such caching pattern, I wonder why MAX_BUILDER_SIZE
is so small? Setting it to, let's set 2kB, wouldn't be better? It would prevent from creating bigger StringBuilder
instances with a quite little memory overhead.
It is a per-thread cache so a low number is expected. Best to use the Reference Source for questions like this, you'll see the comments as well, which looks like (edited to fit):
// 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" is a wee bit puzzling. Well, not really, surely this work was done to optimize Visual Studio. Neelie Kroes would have a field day and the EU would have another billion dollars if she would find out :)
这篇关于了解.NET内部StringBuilderCache类配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!