J'ai toujours cru que le jeu de données consomme plus de mémoire qu'une liste générique. Je teste un test de chargement d'une liste de données et de chargement d'une requête SQL Server. Dans ce cas, le jeu de données consomme moins de mémoire. Je reçois les meilleures lignes et il y a 134 champs par rangée. Un champ binaire et le reste sont la norme Varchar, Int, Bit et ainsi de suite.
Comment dans le monde pourrait-il avoir une donnée avec tout ce qu'il est surcharge consommer moins de mémoire que la liste? Le GC rapporte environ 4 Mo avec DataTable et 5 Mo avec la liste. P>
J'ai testé avec quelques-unes des tables Northwind et la liste était légèrement plus petite dans ces cas. p>
3 Réponses :
juste hors de curiosité, essayez d'appeler Trimexcess sur la liste, puis vérifiez la mémoire. Je doute que cela ferait une énorme différence, mais je soupçonne que cela fera une certaine différence. P>
Fondamentalement, une liste augmente en lots. Cela ne pousse pas à chaque fois que vous ajoutez un objet, il s'agit plutôt d'une certaine quantité, puis si elle en a besoin de plus, elle alloue plus. Je suis curieux s'il y a un espace supplémentaire dans votre liste que vous n'utilisez pas. P>
J'ai reçu le même résultat, malheureusement. Je n'ai pas pensé à ça, gentil post.
Notez que la trimexcess ne fait que n'importe quoi si la quantité d'éléments de la liste est inférieure à 0,9 fois la longueur de la matrice. Cela pourrait être la différence entre 5 Mo et 4,5 Mo ... expliquer un ensemble de 1 Mo de différence de cette façon est un stretch cependant.
Comme la liste elle-même n'est pas plus grande que quelques kilobytes, il n'est pas surprenant qu'il n'y ait aucune différence notable pour la couper. La liste ne contient que des références, les éléments inutilisés ne sont que des références nulles, pas des références à des tableaux vides.
J'avais supposé que la liste réelle était de 5 Mo. Sinon, la mesure complète est inutile.
C'est une illusion. D'une manière ou d'une autre, le GC ne vous donne pas la bonne valeur, peut-être parce qu'il y a des objets qui ne sont pas encore collectés. Peut-être que le chargement d'une table de données provoque des objets plus intermédiaires, ce qui provoque une autre collection de déchets. P>
Votre liste de tableaux stockez les données de la même manière que la table de données, mais sans la surcharge des informations supplémentaires que la table de données et chaque ligne de données contiennent. P>
Si vous voulez que ce soit plus efficace de mémoire, vous devez créer une classe pour un enregistrement de données, de cette façon, vous pouvez stocker les types de valeur comme des valeurs claires au lieu de la boîte en boîte dans des objets. Un Int, par exemple, utilise 20 octets quand il est en boîte mais seulement 4 comme une variable de membre simple. P>
Intéressant, j'ai essayé d'appeler GC.Collect directement après avoir chargé la liste, malheureusement, cela n'a pas changé le résultat. J'ai utilisé GC.Collect (GC.MAXGeneration, GCCollectionMode.Forced) ;. Je vais jouer avec les boxings. Je n'ai pas pensé à ça, merci. J'essayais de le garder générique en utilisant GetValues. Je regarde la mise en œuvre de DataRow et son utilisation de Datastorage pour contenir des valeurs non un objet [] comme je l'ai supposé. Je n'ai jamais entendu parler de la classe Datastorage, peut-être que cela aiderait. Merci pour l'aperçu! +1
Vous avez raison, c'était la boxe consommant la mémoire supplémentaire. Je viens d'essayer de charger les valeurs de la ligne dans des listes génériques et des listes de formulaires utilisent des types de données primitifs non nullables. La mémoire était de 3,8 Mo. Le datatable était de 4,4 Mo. Bon appel!
Pour moi, cela s'est passé dans l'inverse. Eh bien, je n'atteignais pas les données de la base de données, mais je appuyais des données à la base de données à l'aide de Bulk-Insert. Tout en traçant des données, je reçois environ 50 millions d'enregistrements comme une sortie que je souhaitais stocker dans la base de données. J'ai utilisé une insertion en vrac avec des rangées de 200K par push à l'aide de DataTable (comportant seulement 8 colonnes) et constaté que pour chaque insert, il a fallu environ 95 Mo de données (outils de surveillance réseau utilisés et sérialisateur pour trouver la taille de l'objet). Lorsque j'ai utilisé la liste (à l'aide de l'idatatreader) sur un insert en vrac, il a chuté la taille d'une moyenne (une poussée) à 15 Mo moyenne (série utilisée pour trouver la taille de l'objet et surveillé dans le gestionnaire de tâches). Le temps pris pour le traitement et le téléchargement des données à l'aide de DataTable était de 1657 secondes et il est tombé à 850 secondes à l'aide de la liste. p>