Pergunta

Alguém já realmente stackalloc usado durante a programação em C #? Estou ciente do que é não, mas a única vez que ele aparece no meu código é por acaso, porque IntelliSense sugere que quando eu começar a digitar static, por exemplo.

Embora não está relacionado com os cenários de uso de stackalloc, eu realmente fazer uma quantidade considerável de interoperabilidade legado em meus apps, assim de vez em quando eu poderia recorrer ao uso de código unsafe. Mas, no entanto eu costumo encontrar maneiras de unsafe evitar completamente.

E uma vez que o tamanho da pilha para um único segmento em .Net é ~ 1Mb (me corrija se eu estiver errado), estou ainda mais reservados de usar stackalloc.

Existem alguns casos práticos onde se poderia dizer: "este é exatamente a quantidade certa de dados e processamento para mim ir stackalloc inseguro e uso"

Foi útil?

Solução

A única razão para usar stackalloc é o desempenho (tanto para cálculos ou interoperabilidade). Usando stackalloc em vez de uma matriz de pilha alocada, você cria menos pressão GC (GC precisa correr menos), você não precisa de fixar as matrizes para baixo, é mais rápido para alocar do que uma matriz de pilha, um é automaticamente libertado sob saída método (pilha alocada matrizes só são desatribuído quando corre GC). Também usando stackalloc em vez de um alocador nativa (como malloc ou o equivalente .Net) você também ganha velocidade e desalocação automática na saída escopo.

Em termos de desempenho, se você usar stackalloc você aumenta muito a chance de acertos do cache da CPU devido à localidade de dados.

Outras dicas

Eu tenho usado stackalloc para alocar buffers para [próximo] em tempo real DSP trabalho. Foi um caso muito específico, onde o desempenho necessário para ser o mais consistente possível. Nota que há uma diferença entre a consistência e rendimento geral - neste caso eu não estava preocupado com alocações de heap sendo muito lento, apenas com o não determinismo de coleta de lixo naquele ponto no programa. Eu não iria utilizá-lo em 99% dos casos.

stackalloc só é relevante para o código inseguro. Para código gerenciado você não pode decidir onde alocar dados. Tipos de valor são alocados na pilha por padrão (a menos que sejam parte de um tipo de referência, caso em que eles são alocados na pilha). tipos de referência são alocados na pilha.

O tamanho da pilha padrão para uma aplicação simples de baunilha NET é de 1 MB, mas você pode mudar isso no cabeçalho PE. Se você está começando tópicos explicitamente, você também pode definir um tamanho diferente através da sobrecarga de construtor. Para aplicações ASP.NET o tamanho da pilha padrão é de apenas 256K, que é algo a ter em mente se você está alternando entre os dois ambientes.

stackalloc inicialização de spans. Nas versões anteriores do C #, o resultado de stackalloc só poderia ser armazenado em uma variável local ponteiro. A partir de C # 7.2, stackalloc pode agora ser usada como parte de uma expressão e pode ter como alvo uma extensão, e que pode ser feito sem usar a chave inseguro. Assim, em vez de escrever

Span<byte> bytes;
unsafe
{
  byte* tmp = stackalloc byte[length];
  bytes = new Span<byte>(tmp, length);
}

Você pode escrever simplesmente:

Span<byte> bytes = stackalloc byte[length];

Esta é também extremamente útil em situações onde você precisa de algum espaço de rascunho para executar uma operação, mas querem evitar a alocação de memória heap para tamanhos relativamente pequenos

Span<byte> bytes = length <= 128 ? stackalloc byte[length] : new byte[length];
... // Code that operates on the Span<byte>

Fonte: C # - Tudo sobre Span: Explorando um novo .NET Mainstay

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