Pergunta

Quando eu estava olhando assemblies .NET descompilados para ver alguns detalhes internos, notei coisas interessantes StringBuilderCache classe usada por vários métodos do framework:

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

Exemplo de uso que podemos encontrar, por exemplo, em string.Format método:

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);
}

Embora seja bastante inteligente e com certeza me lembrarei desse padrão de cache, me pergunto por que MAX_BUILDER_SIZE é tão pequeno?Definindo para, vamos definir 2kB, não seria melhor?Isso impediria a criação de maiores StringBuilder instâncias com pouca sobrecarga de memória.

Foi útil?

Solução

É um cache por thread, portanto, um número baixo é esperado.Melhor usar o Fonte de referência para perguntas como essa, você também verá os comentários.O que parece (editado para caber):

    // 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" é um pouco intrigante.Bem, na verdade não, certamente este trabalho foi feito para otimizar o Visual Studio.Neelie Kroes teria um dia cheio e a UE teria mais um bilhão de dólares se ela descobrisse :)

Outras dicas

A maioria das strings construídas são provavelmente pequenas, portanto, usar um tamanho de buffer relativamente pequeno cobrirá a maioria das operações sem usar muita memória.Considere que existe um conjunto de threads com possivelmente muitos threads sendo criados.Se cada um deles ocupasse até 2kB para um buffer em cache, isso resultaria em uma certa quantidade de memória.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top