O ConcurrentDictionary
código-fonte menciona a possibilidade de usar TAlternateKey
, que é uma estrutura de referência.
https://github.com/dotnet/runtime/blob/main/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs
Além disso, depois de alguma pesquisa, encontrei outros exemplos interessantes. Como aqui: https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs
#if NET9_0_OR_GREATER
private readonly ConcurrentDictionary<string, CacheEntry>.AlternateLookup<ReadOnlySpan<char>> _stringAltLookup;
public CoherentState()
{
_stringAltLookup = _stringEntries.GetAlternateLookup<ReadOnlySpan<char>>();
}
#endif
//...
#if NET9_0_OR_GREATER
internal bool TryGetValue(ReadOnlySpan<char> key, [NotNullWhen(true)] out CacheEntry? entry)
=> _stringAltLookup.TryGetValue(key, out entry);
#endif
#if NET9_0_OR_GREATER
private readonly ConcurrentDictionary<string, CacheEntry>.AlternateLookup<ReadOnlySpan<char>> _stringAltLookup;
public CoherentState()
{
_stringAltLookup = _stringEntries.GetAlternateLookup<ReadOnlySpan<char>>();
}
#endif
Devo usar ReadOnlySpan<char>
como chave em ConcurrentDictionary
vez de string
para melhor desempenho?
Por si só, seu uso
AlternateLookup
não trará nenhum benefício de desempenho; você só deve considerar usá-lo quando estiver enfrentando casos específicos de ineficiências que ele foi criado para resolver.O mais comum desses problemas é usar
Dictionary<string, TValue>
chaves que são compatíveis comstring
, mas que não são instâncias destring
:Observe a chamada para
ToString
which, que é necessária para obter o tipo de chave apropriado. Embora você deva usar um tipo imutável comostring
para maior robustez, isso tem desvantagens neste caso, pois tudo o que você quer é usar algo compatível comstring
em termos de igualdade (e hash):Agora, graças a
AlternateLookup
, você pode manipular o dicionário diretamente. É claro que isso só funciona se o comparador suportarReadOnlySpan<char>
(e, inversamente, você pode tornar seus próprios comparadores compatíveis com esse mecanismo se tiver um caso que precise ser otimizado).Em suma, usar
AlternateLookup
é vantajoso apenas se você já tiver algo compatível com o tipo de chave (neste caso, uma sequência arbitrária de caracteres) e, caso contrário, precisaria convertê-lo para o tipo correto para garantir a correção de tipo. Se o que você começou com umstring
, não adianta usarAlternateLookup
apenas para usarReadOnlySpan<char>
em vez disso.