7
votes

Limite de mémoire .NET Stack

J'utilise C #, .NET 4.0, 64 bits. J'ai besoin de stocker dans la mémoire 500 millions de "points de données" utilisés dans des calculs. Je dois décider de les créer comme des objets de struct ou de classe. Les structures semblent tellement plus rapides.

Y a-t-il une limite de mémoire pour la pile? Si oui, comment peut-il être ajusté?

stockera autant de données sur une pile affectera les performances globales du système?

(Au fait, je suis conscient de la limitation de la taille d'un objet mono-objet dans .NET, c'est donc adressé - les données seront stockées dans plusieurs collections).


3 commentaires

Êtes-vous sûr que vous ne confusez pas la pile avec le tas?


Sur quelle base réclamez-vous / supposez-vous que les structures sont «tant plus rapides» que des classes?


Je suppose que OP crée une relation difficile entre l'allocation de pile et la structure, ce qui ne va pas. Ce sont des sujets complètement différents, que pourrait être associé.


4 Réponses :


1
votes

vous pourrait utiliser des classes pour vos points de données. Dans ce cas, la mémoire sera allouée sur le tas.

Mais compte tenu de savoir que vous parlez de 500 millions de points de données, et surtout que vous programmez dans le monde .NET avec une limite de mémoire plus restreinte pour les applications, j'encourageais vivement à utiliser une sorte de base de données intégrée, comme SQLite, pour Exemple. De cette manière, vous éviteriez de disposer de tous vos points de données en mémoire simultanément, mais uniquement ceux dont vous avez besoin pour calculer maintenant . .


4 commentaires

D'après mon expérience, il est courant de nécessiter un accès rapide à de grandes quantités de données sans la surcharge d'une base de données. Et si vous les chargez tout en mémoire, vous obtenez 12 Go de frais généraux juste pour utiliser des types de référence. Pas gentil.


@CODEINCHAOS: D'accord. Infact Ne les chargez pas tout en mémoire, comme suggéré, mais utilisez un calque dB pour détenir des données.


Souvent, vous voulez les tenir tous en mémoire pour des raisons de performance. Par exemple, je travaille souvent avec des simulations de physique où des dizaines de gbs de données sont conservées dans de grandes matrices.


@Codeinchaos: objets 500mln? Dans mon expirience où j'ai rencontré une charge de travail de telles dimensions, il n'a généralement pas répondu aux exigences en matière de performance en temps réel. Disons que cela pourrait être vrai pour 99% des cas. Honnêtement, Don-'t pense que 1% est affaire de la question de l'OP :) +1



4
votes

Vous allez stocker vos données dans les tableaux et les tableaux sont toujours stockés sur le tas. Donc, peu importe que vous utilisiez ou non des structs ou des classes pour contenir ces tableaux. Vous voudrez peut-être bien vous assurer que vos points de données sont des types de valeur (c'est-à-dire des structures) de sorte que les matrices de points de données puissent être attribuées efficacement dans des blocs de mémoire contigus de la mémoire.

Les différences de performance entre le tas et la pile La mémoire allouée sont les plus susceptibles d'être vues avec de petits objets alloués et traités dans un court de temps. Pour les objets de taille de longue durée que vous décrivez, je vous attendrais à ce qu'il n'y ait aucune différence de performance entre la pile et la mémoire allouée en tas.


11 commentaires

La chose est que si la structure est allouée sur le tas, il perd son "avantage" (du point de vue de la question) des allocations rapides.


@Tigran Ces différences vont être incontournables une fois que vous avez effectué une opération sur 500 millions de points de données.


@Tigran non si cela fait partie d'un tableau. Les structures se retrouveront dans un bloc de mémoire continue dans la matrice, tandis que les classes obtiendront une nouvelle instance (avec la surcharge de 16 octets associée) et des indirections supplémentaires.


@Codeinchaos: Donc, la structure allouée sur le tas ou sur la pile a la même performance, uniquement si elle fait partie du tableau ??


@ Types de valeur de TIGRAN sont incorporés dans une structure contenant. Peu importe si c'est la pile, une classe ou un tableau. Les types de référence ne incorporent qu'un pointeur dans la structure contenant. Vous devriez lire un peu sur quels types de valeur sont. Eric Lippert a beaucoup écrit à ce sujet, à la fois sur son blog, et ici.


@Codeinchaos: Je suis parfaitement conscient des différences d'entre eux. Ma quesion n'a rien à voir avec ça. Je demande pourquoi pensez-vous que la structure allouée sur le tas et la même forme la structure allouée sur la pile devrait avoir non toute différence en termes de performance? Parce que ce que j'ai compris de votre commentaire avant.


@Tigran, car la prestation des structures est sans rapport avec le tas vs de pile. Il s'agit d'éviter les frais généraux d'une allocation par objet.


Comprenez votre point, mais n'acceptez pas de choisir la structure pour des éléments de 500 mln sur lesquels vous devriez faire un calcul. Immagine Acessing que la lecture de données / rédaction / mise à jour .... i irait certainement pour le type de référence avec la solition fournie dans ma réponse.


@Tigran Un tableau de structures est un type de référence alloué sur le tas


@David Heurferman: Aujourd'hui, j'ai vraiment une difficulté à exprimer mon Thought clairement :) Je veux dire que l'accès à des types de valeur à l'intérieur de la matrice vous fera une copie de ceux de tous les acess en lecture / écriture.


@Tigran uniquement si vous effectuez explicitement une copie du type de valeur.



7
votes

Vous posez la mauvaise question. Si la taille de la pile importe, vous faites quelque chose de mal.

Si vous utilisez de nombreux types de données, vous les mettez dans une collection, telle qu'une matrice. Les tableaux sont toujours alloués sur le tas. Un éventail de structures intègres les structures individuelles et forme un bloc de mémoire continue. (Si vous avez plus de 2 Go, vous avez besoin de plusieurs tableaux).

alors qu'avec des types de référence, le tableau ne contiendra que les références et les objets sont alloués individuellement sur le tas. Une allocation de tas a environ 16 octets de frais généraux, la référence dans le tableau représente une autre 8.
Vous allez également empirer la localité de cache en raison des indirections et le GC doit faire plus de travail, pour ramper toutes ces références.

Ma conclusion est que si vous avez de nombreux petits types de données, faites-en une structure et mettez-les dans un tableau.


0 commentaires

1
votes

Il est surprenant que personne ne semblait essayer de répondre à la question réelle.

Je comprends absolument strong> que c'est la mauvaise question à demander 99,9% du temps, mais il serait toujours intéressant Connaître les résultats (au moins j'étais curieux). P>

Le programme de test h2>

Il est vraiment simple à l'aide de Code dangereux et du mot-clé CODE> SPACALALLOC P>

Thread testThread = new Thread(() =>
{
    for (int i = 1000; i < Int32.MaxValue; i+=1000)
    {
        StackCheck(i);
        Console.WriteLine($"Successfully allocated {i} bytes on the stack");
    }
}, 200_000_000);
testThread.Start();
testThread.Join();


0 commentaires