9
votes

Liste <> mieux à init avec une capacité maximale et utilisez uniquement une fraction de celle-ci, ou init sans capacité

J'ai une liste que je suis initialisée pour être vide et que je vais remplir cette structure dans une boucle comme je analysais les données. Je sais qu'il existe un nombre maximum d'entrées possibles qui seront insérés dans cette liste. Pour le moment, disons 1000. Cependant, après ma analyse des 1000 entrées, je ne pouvais finir que 2 dans la liste. Devrais-je initialiser la liste d'une capacité de 1000 ou ne spécifiez pas de capacité et d'ajouter quelques entrées. Cela pourrait cependant finir par ajouter tous les 1000. Quelle est la meilleure performance sage?


0 commentaires

6 Réponses :


22
votes

n'aimait pas vraiment. Ne pas micro-optimiser. Seulement définir la capacité si vous avez une bonne idée, c'est à peu près le montant dont vous avez besoin. Sous la capuche, la liste double chaque fois qu'elle grandit, le nombre de changements est donc O (journal (n)) . Il devrait être assez efficace.


1 commentaires

Et si vous ne le croyez pas, regardez la méthode assureCapacité de la liste référencesSource.microsoft.com/#mscorlib/system/collections/...



-1
votes

Probablement la meilleure chose à faire est de compromettre. Initialiser la liste à quelque chose comme 256.


0 commentaires

9
votes

Si cela peut vraiment varier considérablement, vous ne voudrez pas définir la capacité. Pour la plupart des collections, la capacité double telle qu'elle est remplie (avec une capacité par défaut de 16, je crois), de sorte que votre capacité s'approche de votre maximum de près lorsque vous le remplissez.


1 commentaires

La valeur par défaut est 0, puis redimensionnée à 4. à partir de .net code source: int Num = this._items.length == 0? 4: this._items.length * 2;



1
votes

Considérant que votre liste est petite pour commencer, vous feriez mieux de ne pas l'initialiser. Il facilitera le code de lire sans succès de performances notable.


2 commentaires

Je devrais dire qu'il est discutable si cela rend le code plus lisible. Il n'y a vraiment pas beaucoup de différence. nouvelle liste () vs nouvelle liste (64)


@Chaospandion: Mais c'est moins maintenu.



3
votes

Premièrement, vous devriez simplement la mettre en œuvre de manière la plus naturelle, maintenable et lisible. Dans ce cas, il s'agit simplement de créer une nouvelle liste (accepter la capacité par défaut) et y ajouter vos objets. Ensuite, ce que vous faites si votre application ne répond pas à vos spécifications de performance, c'est votre profil. S'il s'avère dans le profilage selon lequel il s'agit d'un goulot d'étranglement dans votre application, vous essayez de l'optimiser. Si votre application répond à vos spécifications de performance ou si cette partie spécifique n'est pas un goulot d'étranglement, vous l'ignorez.

Deuxièmement, les détails de la mise en œuvre sont parfois importants et voici un cas où il se trouve. La manière dont est implémentée est une matrice à griffonner de manière dynamique le démarrage avec une certaine capacité et double la taille à chaque fois que la repousse est nécessaire. Cela signifie que si vous ajoutez un objet n dans une liste nouvellement créée, il y aura O (journal n) repousse et vous gaspillerez au plus o (n) espace. À moins que la mémoire ne soit serrée sur votre système (peut-être que vous exécutez .NET CF sur un téléphone mobile) Ce n'est pas si grand d'une affaire. Et à partir d'une perspective de performance, l'analyse de vos entrées est susceptible de consommer beaucoup plus de temps que la repousse. Ainsi, ce n'est pas non probablement un facteur.


0 commentaires

1
votes

Tout d'abord, je ne suis pas dans un tel endroit pour écrire une réponse, je suis d'abord venu le trouver, mais j'écris un, juste pour suggérer, et aussi avoir votre opinion.

Qu'est-ce qu'un la liste fait lors de l'ajout de données: xxx

en regardant cela, il fait d'abord exactement ce que certains d'entre vous ont dit, il double la capacité et contrairement à d'autres personnes peuvent penser, et aussi Contrairement à la manière dont les matrices fonctionnent, il ne bloquera pas l'utilisateur lorsqu'il atteint la capacité fournie.

et quand augmente-t-il la capacité? À cette ligne: capacité = newcapacité; ; En réalité, il s'agit du constructeur de capacité de capacité qui effectue les opérations: xxx

Comme il est évident que ce n'est pas une simple opération de changement d'indicateur pour simplement laisser plus d'articles dans, comme quelle liste liée fera ( Pour être honnête, je considère toujours des listes comme linkedlist '. Maintenant, je peux dire avec la liste, j'ai mieux lu performance, et moins de performances d'écriture (mais je ne suis pas sûr de ce que je dis, quelqu'un confirme si nous devons utiliser LinkedList quand Nous effectuons des opérations d'écriture et d'une fois.)). Ainsi, comme nous pouvons le constater, cela crée un nouveau tableau et copier des éléments sur une nouvelle liste une par une ...

Voici ma suggestion:

  1. Comme @jason dit, nous n'avons pas besoin de penser à la transmission d'une valeur, lorsque nous ne pourrons exécuter que notre opération d'écriture une fois, dans la liste
  2. Si le poids de la liste est petit, par exemple, juste une certaine itération d'augmentation de la taille de la liste ne fera pas grand chose, par exemple comme tout le monde, si c'est 2 devenue 4, et 8 ... Tout d'abord, ce n'est d'abord pas Triple Time que nous augmentons la taille, et deuxièmement, nous ne copions que quelques données. Encore une fois, nous pouvons l'ignorer, peu importe où le code est placé, ou j'espère.
  3. Mais si vous copiez quelques milliers de données de DB, et commence à partir du début, 2-> 4-> 8-> 16-> 32-> 64-> 128-> 256-> 512- > 1024-> 2048 -> ... Jusqu'à ce que nous ayons eu une taille de matrice croissante de 10 fois, et si nous pensons qu'une copie est une seule opération qui copie la référence, à part les autres choses qui doivent être effectuées dans des codes de machine, nous aurons 4094 fois de copier des données d'une Tableau à un autre et consommer également la moitié d'une grande partie de l'espace qui doit attendre que GC (dans une application graphique peut devenir une affaire, mais c'est trop pour moi d'écrire un exemple pour) ... Donc, en multipliant cela par nombre d'opérations qui appellent ce code en même temps, les performances peuvent réduire considérablement. Donc, je peux envisager de procéder à ce qui suit: Si je connais un numéro, je sais par exemple que j'ai x article, et que ces éléments peuvent faire référence à 0 ~ 2, je peux envisager de passer à ce que x ou x * 2, et cela ne se développera qu'une fois si besoin. (S'il vous plaît dites-moi votre avis).

  4. achèvement à l'achèvement de l'idée n ° 3 Le doublement semble être raisonnable par liste unique, et peu importe ce que vous faites, vous ne pouvez que stimuler la moitié de l'époque et que tout le fonctionnement ne prendra que prendre ~ Deux de ces moitiés, vous pouvez donc l'ignorer si vous ne lancez pas plusieurs threads / tâches en même temps, ou beaucoup de la liste l'une après l'autre.

    Je viens de savoir aussi que: privé const int _defaultcapacité = 4;

    Note: que si vous Utilisez une capacité maximale, comme il l'a dit, il stocke l'espace égal au montant est nécessaire pour des éléments 2G (comme indiqué: // permet à la liste de croître à une capacité maximale possible (~ 2g éléments) avant de rencontrer débordement. ), et ce n'est pas le montant que vous souhaitez initialiser votre liste, même si votre code est exécuté une fois, il ressemble à trop de données droites (linéaires / côte à côte) à l'intérieur de la RAM (comme la structure de données nous le pensait, si C # n'a rien fait plus récent que ce que nos livres ont dit) et l'allocation peut également nécessiter un certain temps (je ne suis pas au courant de ce processus). Donc, je ne le recommande jamais, si vous ne savez pas vraiment que combien de temps est requis, et je pense que nous devrions également envisager une liste liée, si les données sont vraiment linéaires, et il peut y avoir beaucoup d'espace pris en RAM en aléatoire Lieux (si c'est le cas: cela nécessite beaucoup de vérification avant que la machine puisse trouver un endroit pour allouer cet espace dans).


0 commentaires