7
votes

Utilisation de la mémoire, sélection de la liste VS Liste Problème

J'utilisais SortedList () dans une classe qui stocke environ 15-100 000 données.

Récemment, mes exigences ont été modifiées, les données ne doivent plus être stockées comme triées, donc je suis passé à la liste ().

Cependant, dans ce cas, j'ai remarqué que la liste () consomme environ 20% + plus de mémoire.

Articles 9k:

  • LIEDLIST: 105MB
  • Liste: 125MB

    Articles 15K:

    • SORTEDLIST: 115MB
    • Liste: 140 Mo

      Dans l'environnement que je développe, la mémoire est assez cruciale. Au lieu de la liste () Que puis-je utiliser pour éviter cette consommation de mémoire supplémentaire et avoir toujours une liste non triée?

      p. J'utilise un hashset (de chaîne) pour fournir une vérification de l'unicité lors de l'utilisation de la liste (de) pour simuler la tritedlist.Containskey () bien que je ne pense pas que cela puisse apporter de telles tarifs de mémoire.

      p. 2: Mon application a environ 80 Mo d'allocation de mémoire de base dans le démarrage. Les chiffres doivent donc lire comme 105-80 = 25, 125-80 = 45 et ainsi de suite sur

      résultats

      Merci pour toutes les réponses, les résultats finaux sont les suivants:

      • Vous devez définir la bonne capacité à enregistrer la mémoire
      • Hashset est très mauvais sur la mémoire et consomme beaucoup plus que des attentes. C'était le problème. En quelque sorte sortiesList () parvient à utiliser moins de mémoire pour une fonctionnalité similaire.

        Certains Bencmarks: 500 caractères, 250000 insert

        Liste (de chaîne) (50000)

        274 ms - 226 mb

        triédlist (de chaîne, chaîne) (50000)

        34868 MS - 230 Mo

        hashset

        420 ms - 232 Mo

        Dictionnaire (de chaîne, objet)

        486 ms - 234 MB

        Bien que quand je l'ai changé le nombre a diminué à 25, puis:

        hashset pour 600.000 Itération 300 MB où Liste () est de 286 Mo

        En outre sur l'utilisation de la mémoire HashSet: http: //blog.mischel. com / 2008/04/09 / HashSet-limites / Dictionnaire (de ficelle, objet) n'a pas été beaucoup mieux soit dans mon test.


12 commentaires

D'où avez-vous reçu ces valeurs?


À partir de mon application de test, bien que la mémoire puisse la mémoire de base de la mémoire - d'environ 80 Mo).


Du chef de la tâche (ou similaire)? Essayez d'utiliser un profileur (comme CLRProfiler: Microsoft. com / téléchargements / ... ). Les données de la mémoire du gestionnaire de tâches dépendent du comportement de la collecte des ordures.


Je m'attendrais à ce que l'empreinte de la liste de la liste () est à propos de "Tailleof (t)" * Capacité de la liste (pouvant être vérifiée). Si T est une classe, que vous ne stockez que des références, je m'attendrais donc, cette empreinte réelle de votre liste est minimale (15k articles * 4 octets), peut-être quelque chose d'autre qui a changé, cela a plus que les données elles-mêmes ?


Ignorer mon dernier commentaire si ces données sont venues d'un profileur ...


@Ravadre: En fait, étant donné que la liste est basée sur une matrice, il y a toujours des emplacements vides. Vous pouvez donc vous attendre à ce que quelque chose de 15k * (taille de référence) à 30k * (taille de référence).


@Martinho Ces chiffres sont cohérents et pas seulement des rapports d'une fois. Cela fonctionne pendant 5 minutes environ. Donc, je peux regarder régulièrement la croissance et comparer.


@Martinho: C'est pourquoi j'ai mentionné la capacité, non de longueur, car la capacité vous donne la quantité de telles machines à sous, qui sont attribuées par la liste et non le nombre d'éléments. Par conséquent, c'est toujours la capacité * 15k :)


@Ravadre c'est des références. SortedList () a également eu des clés de chaîne. Mais la liste () utilise hashset () pour stocker les mêmes clés de chaîne.


@Ravadre Data est exactement la même chose, je viens de changer mon héritage de classe de la sélection () à la liste () et la mémoire augmente.


@dr. Evil - et que se passe-t-il si vous lancez un jeu de hasch Uut, il suffit de garder la liste? La liste est en fait un tableau sous le capot (comme dit Martinho), donc même si vous allouez de l'espace pour des éléments 300K, il reste environ 1,2 Mo uniquement (2,4 Mo sur 64 bits), la liste elle-même ne peut pas consommer beaucoup de mémoire. Les données ou autres structures, comme les ensembles de hachages doivent


Je peux supprimer le hashset mais n'a pas d'importance car au lieu de hashset, la même chaîne sera stockée en tant que clé de liste triée. Donc, wather wat ce sont les mêmes données stockées.


6 Réponses :


2
votes

Si vous avez déjà un hashset de votre collection, je ne sais pas pourquoi vous avez également besoin d'une liste, mais si vous recherchez un conteneur qui garantit une fonctionnalité unicité et contenant (), pourquoi pas un dictionnaire générique?

Quelle que soit votre décision sur les questions ci-dessus, l'utilisation de quelque chose comme le gestionnaire de tâches est trop inexacte pour prendre des décisions sur la consommation de mémoire dans .NET. Si vous ne l'avez pas déjà fait, saisissez un essai de Profileur de mémoire .NET SCITECH ou Profiler et exécutez votre application. Prenez un instantané de votre utilisation de la mémoire avant de charger votre ensemble et juste après la comparaison. Vous pouvez le faire avec plusieurs types de collecte pour mesurer l'utilisation de la mémoire relative de chacune de manière très précise.


1 commentaires

+1 pour recommander l'utilisation d'un profileur pour obtenir des données précises.



9
votes

Prévenez-vous la liste Liste code> Capacité?

Petite expérience que j'ai faite: p>

Ce programme prend ~ 640MB p> xxx pré>

Ce programme prend ~ 320 Mo P>

List<int> list = new List<int>(100000000);

for (int i = 0; i < 100000000; i++)
{
    list.Add(i);
}


7 commentaires

+1 Il s'agit d'une excellente observation car une liste préélocalisée prendra un bloc de RAM contigu à la fois s'il le peut et réduira la surcharge générale générée par la fragmentation de la mémoire.


Très bon point, je vais essayer maintenant. Le même problème n'existe pas pour la tri ()?


Tous les conteneurs ayant la propriété «capacité» doivent être définis pour une performance optimale.


Ce que j'essaie de dire que cela devrait être non pertinent dans cette affaire de comparaison depuis que je comparais la liaison () et la liste () et ne l'a pas prélevé.


La liste est également optimisée pour tout stocker dans un bloc de continue, je ne sais pas à quel point la tri est mise en œuvre. Vous devrez vérifier pour vous-même. N'oubliez pas de signaler les résultats :)


Je vous ferai savoir que la capacité de BTW fait une énorme différence, merci pour la pointe.


Apparemment, le problème se passait en fait à cause de Hashset () Il utilise une quantité énorme de mémoire. Maintenant, j'ai besoin de trouver un meilleur type de données pour stocker cette clé unique.



1
votes

HASHSETS (& HASHTABLES) Utilisez beaucoup de mémoire! Beaucoup plus qu'une simple liste / type de tri


2 commentaires

Un dictionnaire utilise deux fois plus de mémoire en interne comme une liste (50% plus sur un système 64 bits), la différence n'est donc pas si grande.


Eh bien, ce n'est pas exactement 50%. Les hashables ne sont jamais pleines à 100%, elles sont reformulées lorsqu'elles atteignent 70%. Les listes sont seulement redimensionnées lorsque elles sont complètement pleines.



3
votes

A Liste avec des éléments de 9k aurait une capacité comprise entre 9k et 18k, de sorte que les frais généraux de ces éléments seraient compris entre 36 et 72 kilobytes (le double sur un système 64 bits).

Clairement, le 72 Ko n'est même pas proche de la différence de 20 Mo que vous voyez, de sorte que l'utilisation de la mémoire de la liste elle-même ne peut pas être la cause. Compte tenu de savoir que la liste triée doit également conserver une référence à chaque objet, de sorte que l'utilisation de la mémoire devrait être identique.

Donc, soit il y a autre chose à l'aide de la mémoire, ou vous ne regardez pas l'utilisation de la mémoire réelle de l'application. Si vous recherchez dans le gestionnaire de tâches, vous ne voyez pas la quantité de mémoire utilisée, uniquement à quel point le gestionnaire de mémoire est attribué.


0 commentaires

0
votes

Vérifiez les collections de puissance par Wintellect, l'équivalent .NET pour les collections de type STL. Je crois que le type de jeu devrait vous donner la fonctionnalité dont vous avez besoin (unicité), mais vous devez effectuer les repères à comparaison. Juste mes 2 cents.


0 commentaires

0
votes

Je recommanderais de regarder des listes vitrées ( http://sites.google.com/site/ Glazedlists / ). Celles-ci sont très rapides pour le tri et sont formidables avec la mémoire.


0 commentaires