|
Aposto que você não está usando estas cinco APIs do .NET e pelo menos uma delas pode mudar completamente a forma como você aborda um problema de desempenho. (Traduzido e formatado com ajuda da IA e revisado por Macoratti) |
Dictionary<TKey, TValue>, string, List<T>, Span<T>, todos tipos familiares, todos perfeitamente capazes de levar uma aplicação muito longe.

FrozenDictionary, SearchValues<T>, String.Create(), ReadOnlyMemory<T> ou CollectionsMarshal.AsSpan(). Mas uma vez que você entende para que foram projetadas, elas se tornam ferramentas úteis para ter à disposição quando o problema certo aparecer.FrozenDictionary para Dados de Consulta Somente LeituraDictionary<TKey, TValue> normal é projetado para ser mutável.
var codigosStatus = new Dictionary<int, string>
{
[200] = "OK",
[201] = "Criado",
[400] = "Requisição Inválida",
[401] = "Não Autorizado",
[404] = "Não Encontrado",
[500] = "Erro Interno do Servidor"
};
|
FrozenDictionary<TKey, TValue> existe especificamente para o cenário oposto.
var codigosStatus = new Dictionary<int, string>
{
[200] = "OK",
[201] = "Criado",
[400] = "Requisição Inválida",
[401] = "Não Autorizado",
[404] = "Não Encontrado",
[500] = "Erro Interno do Servidor"
}.ToFrozenDictionary();
|
FrozenDictionary é projetado com a premissa de que você pagará esse custo uma vez e depois realizará muitas consultas posteriormente.FrozenDictionary não é o substituto certo. O custo de reconstruir repetidamente uma coleção congelada anularia o seu propósito.FrozenDictionary é mais rápido que o Dictionary."
É que o tempo de execução pode fazer compromissos diferentes quando sabe que uma coleção nunca mudará.SearchValues<T> para Buscas Repetidas
if (texto.Contains(':'))
{
// ...
}
|
IndexOf() repetidamente para cada caractere.
int virgula = texto.IndexOf(',');
int pontoVirgula = texto.IndexOf(';');
int pipe = texto.IndexOf('|');
int doisPontos = texto.IndexOf(':');
|
SearchValues<T> é projetado para a situação em que você está pesquisando repetidamente por um valor a partir de um conjunto conhecido.
private static readonly SearchValues<char> Separadores =
SearchValues.Create(",;|:");
int indice = texto.AsSpan().IndexOfAny(Separadores);
|
SearchValues<char> reutilizável não vai de repente transformar sua aplicação.SearchValues<T> porque parece mais sofisticado do que IndexOfAny(). Busque por ele quando a busca em si for repetida o suficiente para que preparar os valores de busca tenha a chance de se pagar.String.Create() Quando Construir Strings em Caminhos Críticos (Hot Paths)+ cria uma pilha de strings temporárias.String.Create() se torna interessante.
string id = $"USER-{userId:D8}";
|
string id = string.Create(
13,
userId,
static (span, value) =>
{
"USER-".AsSpan().CopyTo(span);
value.TryFormat(span[5..], out _, "D8");
});
|
String.Create() aloca a string final uma vez e te dá um span gravável sobre o seu armazenamento de caracteres para que você possa populá-lo diretamente.String.Create().String.Create() é algo que você busca quando estabeleceu que a construção de strings e suas alocações são realmente relevantes para a carga de trabalho.ReadOnlyMemory<T> Quando os Dados Devem Sobreviver a um Span<T>Span<T> é um dos tipos mais úteis introduzidos no .NET moderno, mas ele vem com uma limitação fundamental.Span<T> em um campo de classe normal.
public class BufferHolder
{
private Span<byte> _buffer;
}
|
Span<T> é um ref struct, o que significa que o compilador impõe regras estritas sobre onde ele pode viver e quanto tempo pode sobreviver.ReadOnlyMemory<T> se torna útil.
public sealed class Message
{
private readonly ReadOnlyMemory<byte> _data;
public Message(ReadOnlyMemory<byte> data)
{
_data = data;
}
public ReadOnlySpan<byte> Data => _data.Span;
}
|
Span<T> como uma visão temporária e de alto desempenho sobre a memória.Memory<T> ou ReadOnlyMemory<T> como uma representação armazenável dessa memória.Span<T> não pode cruzar com segurança um limite de await, enquanto Memory<T> é especificamente projetado para cenários onde a memória precisa permanecer acessível após o frame de pilha atual ter desaparecido.ReadOnlyMemory<T> não torna magicamente os dados subjacentes imutáveis. Ele apenas previne mutação através daquela visão específica.Span<T> quando precisar de uma visão de curta duração e alto desempenho. Use ReadOnlyMemory<T> quando essa visão precisar ser armazenada ou sobreviver além do escopo síncrono atual.CollectionsMarshal.AsSpan() Quando um List<T> Precisa de Processamento Baseado em SpanList<T> é uma das coleções mais comumente usadas no .NET.
Ela também é suportada internamente por um array.List<T> mas precisa passar seu conteúdo para uma API que trabalha com Span<T>.CollectionsMarshal.AsSpan() te dá acesso direto ao armazenamento subjacente da lista.
var values = new List<int>
{
10, 20, 30, 40, 50
};
Span<int> span = CollectionsMarshal.AsSpan(values);
for (int i = 0; i < span.Length; i++)
{
span[i] *= 2;
}
|
CollectionsMarshal.AsSpan() não é um convite para tratar List<T> como um contêiner de span de propósito geral.CollectionsMarshal.AsSpan() é mais útil quando você já tem um List<T> e precisa fazer a ponte eficiente dele para APIs baseadas em span sem pagar por uma cópia.
E estamos conversados..![]()
"E andai em amor, como também Cristo nos amou, e se
entregou a si mesmo por nós, em oferta e sacrifício a Deus, em cheiro suave."
Efésios 5:2
Referências: