Domine async/await no C# 13: melhore desempenho e clareza
C# 13: Domine Tipos e Otimize o Desempenho do Código
Neste tutorial, você aprenderá como fazer escolhas adequadas de tipos para maximizar o desempenho em aplicações C# 13
O que é C# 13 e por que aprender em 90 minutosExplore as inovações do C# 13 e melhore a legibilidade do seu código. Este tutorial prático de 90 minutos oferece dicas essenciais para desenvolvedores .NET.. Abordaremos desde o uso inteligente de valores e referências até recursos como Span<T>, structs e classes
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC., explorando também boas práticas para reduzir alocações desnecessárias e, assim, otimizar a velocidade de execução.
Entendendo a Importância de Escolher o Tipo Correto🔗
Cada tipo em C# 13
O que é C# 13 e por que aprender em 90 minutosExplore as inovações do C# 13 e melhore a legibilidade do seu código. Este tutorial prático de 90 minutos oferece dicas essenciais para desenvolvedores .NET. possui características de alocação de memória, transferência de dados e tratamento em tempo de execução que influenciam diretamente a performance. Quando falamos em tipos por valor
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. (Value Types), estamos lidando com dados que, em geral, são armazenados na stack (pilha). Já os tipos por referência (Reference Types
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC.) ficam no heap, exigindo acesso indireto por ponteiros internos.
Por que isso importa? Porque toda chamada de método, uso de coleções e até loops de alto volume podem gerar um impacto significativo, acumulado ao longo de milhares ou milhões de iterações.
Struct vs. Class: Quando Usar Cada Tipo🔗
Um debate clássico em C#: struct
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. ou class
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC.? Em C# 13
O que é C# 13 e por que aprender em 90 minutosExplore as inovações do C# 13 e melhore a legibilidade do seu código. Este tutorial prático de 90 minutos oferece dicas essenciais para desenvolvedores .NET., as regras básicas continuam:
- struct
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. (tipo por valor):
- Geralmente aconselhável quando a estrutura é pequena e imutável (ou com poucas mutações).
- Boa para reduzir o overhead de alocação no heap.
- Útil em cenários de alto volume de instâncias ou chamadas frequentes (ex.: game loops ou manipulação de dados sensíveis em processamento intensivo).
- class
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. (tipo por referência):
- Adequada para objetos complexos, com muitos campos ou forte vinculação hierárquica (herança).
- Permite comportamentos polimórficos clássicos.
Uma novidade que facilita a decisão é o maior suporte a tipos record struct e
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC.record class, permitindo criar tipos mais otimizados e com benefícios de boilerplate reduzido, como comparações estruturais (“por valor semântica”) e deconstruction. Entretanto, quando se fala apenas em desempenho, considere se realmente precisa de todos os recursos de uma class
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC.
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. antes de optar por ela.
Usando Span<T> para Evitar Cópias Desnecessárias🔗
O Span<T> permite manipular blocos de memória contíguos sem criar novas alocações. Em vez de copiar arrays ou strings durante operações de slicing e leitura, você trabalha diretamente sobre a mesma região de memória.
Por exemplo, considere este trecho de código para acessar um intervalo de um array:
int[] numeros = { 10, 20, 30, 40, 50 };
// Abordagem sem Span<T>
// Cria um novo array com elementos de índice 1 a 3
int[] subNumeros = numeros[1..4];
// Com Span<T>, reaproveita memória
Span<int> spanNumeros = new Span<int>(numeros);
Span<int> slice = spanNumeros.Slice(1, 3);
// Agora 'slice[0]' corresponde diretamente ao 'numeros[1]'
Benefícios:
- Evita alocações extras e cópias de dados.
- Torna o código mais fluido para manipular fatias de arrays e strings.
- Integra-se muito bem a cenários de alto desempenho, como processamentos de stream ou buffers de rede.
Classes Seladas (sealed) para Evitar Sobrecarga de Herança🔗
Mesmo sendo um recurso já existente antes do C# 13
O que é C# 13 e por que aprender em 90 minutosExplore as inovações do C# 13 e melhore a legibilidade do seu código. Este tutorial prático de 90 minutos oferece dicas essenciais para desenvolvedores .NET., o uso de sealed class continua relevante quando a intenção é bloquear herança e otimizar chamadas de método. O tempo de execução do .NET (CLR) pode efetuar diversas otimizações em classes
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC.
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. seladas, pois sabe que não ocorrerá polimorfismo dinâmico.
public sealed class Calculadora
{
public int Somar(int a, int b) => a + b;
}
Por que selar a classe melhora desempenho?
- O CLR pode fazer inlining e devirtualização de chamadas de métodos em classes
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. sealed, pois não serão sobrescritos. - Reduz a complexidade de possíveis lookups na vtable.
ValueTask Versus Task: Quando Optar pelo ValueTask🔗
Para operações assíncronas que podem terminar de forma imediata ou ter pouco trabalho a ser feito, ValueTask é útil. Diferentemente de Task, que é sempre alocado no heap, um ValueTask pode funcionar como uma struct
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. simples e evitar uma alocação adicional caso o resultado já esteja disponível:
// Exemplo de método que se beneficia de ValueTask
public async ValueTask<int> CalcularAlgoAsync(int x)
{
if (x < 10)
{
// Retorna com computação imediata, sem criar uma Task no heap
return x + 10;
}
// Caso contrário, processa de forma assíncrona
await Task.Delay(100);
return x + 100;
}
Quando usar?
- Em métodos muito simples, chamados com alta frequência.
- Em bibliotecas de baixo nível onde cada alocação faz diferença.
- Se o método for mais complexo ou não for chamado repetidamente, o ganho pode ser mínimo ou inexistente em comparação ao
Task.
Minimizar Boxing e Unboxing🔗
Boxing ocorre quando um tipo por valor (ex.: int, struct,
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC.bool) é convertido para object ou para uma interface
Trabalhando com interfaces e coleções aprimoradas em C# 13Descubra como as implementações padrão em interfaces e coleções aprimoradas do C# 13 otimizam a criação de códigos modulares, seguros e performáticos. implementada por ele. Unboxing é a operação inversa. Em aplicações com intensas operações de conversão, isso resulta em muitas alocações desnecessárias de objetos.
Uma dica para C# 13
O que é C# 13 e por que aprender em 90 minutosExplore as inovações do C# 13 e melhore a legibilidade do seu código. Este tutorial prático de 90 minutos oferece dicas essenciais para desenvolvedores .NET. (e em versões anteriores também) é evitar passes redundantes por object ou interfaces
Trabalhando com interfaces e coleções aprimoradas em C# 13Descubra como as implementações padrão em interfaces e coleções aprimoradas do C# 13 otimizam a criação de códigos modulares, seguros e performáticos. genéricas quando não for essencial. Em vez disso, use tipos genéricos fortes e overloads de método dedicadas a tipos valor, sempre que possível.
Structs Imutáveis e readonly struct🔗
Quando você decide usar struct, considere se ela pode ser imutável. Structs imutáveis previnem modificações acidentais no estado interno, o que favorece otimizações do compilador. Já a palavra-chave
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC.readonly garante que todos os campos da struct
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. são apenas leitura, fornecendo mais segurança para otimizações ao gerar código compilado.
public readonly struct Ponto2D
{
public Ponto2D(double x, double y)
{
X = x;
Y = y;
}
public double X { get; }
public double Y { get; }
}
Benefícios:
- Menos gastos de cópia e defesa de estado.
- Maior clareza de que o valor não será alterado após a criação.
Exemplos de Comparação de Desempenho🔗
Para ilustrar, abaixo está uma pequena tabela de situações de uso onde cada escolha traz impacto no desempenho (valores hipotéticos apenas para exemplificar a ideia):
| Situação | Abordagem Recomendada | Motivo |
|---|---|---|
| Alto volume de acesso a arrays | Span<T> | Evita cópias, reduz alocações desnecessárias |
| Estrutura leve e imutável | readonly struct ou record struct | Elimina overhead de heap, facilita otimizadores |
| Operações assíncronas simples | ValueTask | Evita alocação de Task no heap em cenários de rápido retorno |
| Herança desnecessária | sealed class | Permite otimizações de inlining e devirtualização no CLR |
| Conversões frequentes | Evitar boxing/unboxing por object | Minimiza alocações e tempo de casting |
Conclusão🔗
Nesta etapa do aprendizado, vimos como o uso correto de tipos é essencial para aplicar otimizações de desempenho em C# 13
O que é C# 13 e por que aprender em 90 minutosExplore as inovações do C# 13 e melhore a legibilidade do seu código. Este tutorial prático de 90 minutos oferece dicas essenciais para desenvolvedores .NET., mantendo a legibilidade. Ao prestar atenção às distinções entre struct
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. e class
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC., empregar Span<T> para manipular coleções sem overhead, escolher ValueTask em cenários assíncronos pontuais e selar classes
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. que não requerem herança, você atinge um código mais responsivo, com melhor gerenciamento de memória.
A chave está em entender o seu domínio e escolher o tipo mais adequado às necessidades de cada segmento de código. Pequenos ajustes podem gerar grandes ganhos acumulados em aplicações de grande porte ou em cenários de alta concorrência.
Próximos Passos
- Exercite o uso de
Span<T>em processamento de arrays e strings. - Experimente converter métodos que retornam
TaskparaValueTaske observe os ganhos de performance em cenários simples. - Avalie se faz sentido aplicar
sealed classonde não há necessidade de herança.
Boas práticas de performance e memória para jogos em C# 13Descubra técnicas para otimizar desempenho e uso de memória em jogos com C# 13, utilizando structs, pooling e melhores práticas do GC. - Crie e teste structs e record structs para aproveitar as otimizações oferecidas pelo C# 13
O que é C# 13 e por que aprender em 90 minutosExplore as inovações do C# 13 e melhore a legibilidade do seu código. Este tutorial prático de 90 minutos oferece dicas essenciais para desenvolvedores .NET..
Com essas práticas, você se aproxima de um código robusto, com alta eficiência e pronto para lidar com cenários escaláveis.
Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.
Referências🔗
- Documentação Oficial Microsoft sobre C# - Fornece as bases oficiais e detalhadas sobre a linguagem e os recursos apresentados no tutorial, como tipos de valor, Span<T>, e otimizações no gerenciamento de memória: docs.microsoft.com/pt-br/dotnet/csharp/
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás
há 10 meses atrás