Question

Quelqu'un at-il jamais réellement utilisé stackalloc pendant la programmation en C #? Je suis conscient de ce qui est fait, mais la seule fois où il apparaît dans mon code est par accident, parce que IntelliSense suggère quand je commence à taper static, par exemple.

Bien qu'il ne soit pas lié aux scénarios d'utilisation de stackalloc, je fais en fait une quantité considérable de Interop héritage dans mes applications, de sorte que chaque maintenant et je pouvais recourir à l'aide du code de unsafe. Mais néanmoins, je trouve généralement des moyens d'éviter unsafe complètement.

Et puisque la taille de la pile pour un seul thread en .Net est ~ 1Mb (corrigez-moi si je me trompe), je suis encore plus réservé de l'utilisation stackalloc.

Y a-t-il des cas pratiques où l'on pourrait dire: «c'est exactement la bonne quantité de données et de traitement pour moi d'aller dangereux et utiliser stackalloc »

Était-ce utile?

La solution

La seule raison d'utiliser stackalloc est la performance (soit pour les calculs ou Interop). En utilisant stackalloc au lieu d'un tableau alloué tas, vous créez moins de pression de GC (GC doit fonctionner moins), vous n'avez pas besoin d'épingler les tableaux vers le bas, il est plus rapide d'allouer qu'un tableau de tas, un est automatiquement libéré procédé de sortie (matrices de segment de mémoire alloué ne sont désallouées lorsque GC exécute). Aussi à l'aide stackalloc au lieu d'un allocateur natif (comme malloc ou l'équivalent .Net) vous gagnez également la vitesse et désallocation automatique à la sortie du champ.

Performance sage, si vous utilisez stackalloc vous augmentez considérablement les chances de cache frappe sur la CPU en raison de la localisation des données.

Autres conseils

Je l'ai utilisé stackalloc d'allouer des tampons pour [près] le travail de DSP en temps réel. Ce fut un cas très précis où la performance devait être aussi cohérente que possible. Notez qu'il ya une différence entre la cohérence et le débit global - dans ce cas je pas concerné par les allocations de segments étant trop lent, juste avec le non déterminisme de la collecte des ordures à ce moment-là dans le programme. Je ne l'utiliser dans 99% des cas.

stackalloc ne concerne que le code dangereux. Pour le code managé vous ne pouvez pas décider où allouer des données. types de valeurs sont attribuées sur la pile par défaut (à moins qu'ils font partie d'un type de référence, auquel cas ils sont répartis sur le tas). Les types de référence sont attribués sur le tas.

La taille de la pile par défaut pour une application .NET vanilles est de 1 Mo, mais vous pouvez modifier dans l'en-tête de PE. Si vous êtes fils explicitement à partir, vous pouvez également définir une taille différente par la surcharge du constructeur. Pour les applications ASP.NET la taille de la pile par défaut est seulement 256K, ce qui est quelque chose à garder à l'esprit si vous passez entre les deux environnements.

initialisation de stackalloc de travées. Dans les versions précédentes de C #, le résultat de stackalloc ne pouvait être stocké dans un pointeur variable locale. A partir de C # 7.2, stackalloc peut maintenant être utilisé dans le cadre d'une expression et peut cibler une portée, et qui peut être fait sans utiliser le mot-clé dangereux. Ainsi, au lieu d'écrire

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

Vous pouvez écrire simplement:

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

Ceci est extrêmement utile dans les situations où vous avez besoin d'espace de travail pour effectuer une opération, mais que vous voulez éviter d'allouer la mémoire de tas pour des tailles relativement petites

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

Source: C # - All About Span: Explorer Mainstay un nouveau .NET

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top