50 votes

.NET Integer vs Int16 ?

J'ai une pratique douteuse du codage.

Lorsque j'ai besoin d'itérer à travers une petite liste d'éléments dont la limite de comptage est inférieure à 32000, j'utilise Int16 pour mon i au lieu de Integer. Je fais cela parce que je suppose que l'utilisation de int16 est plus efficace qu'un Integer complet.

Ai-je tort ? N'y a-t-il aucune différence de performance effective (même minime) entre l'utilisation d'un Int16 et d'un Integer ? Devrais-je arrêter d'utiliser Int16 et m'en tenir à Integer pour tous mes besoins de comptage/itération ? (VB OU C#)

Merci d'avance pour tout conseil !

85voto

Alex Lyman Points 7480

Vous devez presque toujours utilice Int32 o Int64 (et, non, vous n'obtenez pas de crédit en utilisant UInt32 o UInt64 ) lors du bouclage d'un tableau ou d'une collection par index.

La raison la plus évidente pour laquelle il est moins efficace est que tous les index de tableaux et de collections trouvés dans la BCL prennent Int32 donc une distribution implicite est toujours va se produire dans le code qui essaie d'utiliser Int16 en guise d'index.

La raison la moins évidente (et la raison pour laquelle les tableaux prennent Int32 comme un indice) est que la spécification CIL dit que toutes les valeurs de la pile d'opérations sont soit Int32 o Int64 . Chaque fois que vous chargez ou stockez une valeur dans un autre type d'entier ( Byte , SByte , UInt16 , Int16 , UInt32 ou UInt64 ), une opération de conversion implicite est impliquée. Les types non signés n'ont pas de pénalité pour le chargement, mais pour le stockage de la valeur, cela équivaut à une troncature et à un éventuel contrôle de débordement. Pour les types signés chaque Le signe de la charge s'étend, et le signe du magasin s'effondre (et il y a un contrôle de débordement possible).

L'endroit où cela va vous nuire le plus est la boucle elle-même, pas les accès aux tableaux. Par exemple, prenez cette boucle d'apparence innocente :

for (short i = 0; i < 32000; i++) {
    ...
}

Ça a l'air bien, non ? Pas du tout ! Vous pouvez en fait ignorer l'initialisation ( short i = 0 ) puisqu'elle ne se produit qu'une fois, mais la comparaison ( i<32000 ) et d'incrémentation ( i++ ) se produisent 32000 fois. Voici un code pesudo pour montrer à quoi ressemble cette chose au niveau de la machine :

  Int16 i = 0;
LOOP:
  Int32 temp0 = Convert_I16_To_I32(i); // !!!
  if (temp0 >= 32000) goto END;
  ...
  Int32 temp1 = Convert_I16_To_I32(i); // !!!
  Int32 temp2 = temp1 + 1;
  i = Convert_I32_To_I16(temp2); // !!!
  goto LOOP;
END:

Il y a 3 des conversions là-dedans qui sont exécutées 32000 temps. Et ils auraient pu être complètement évités en utilisant simplement une Int32 o Int64 .

Mise à jour : Comme je l'ai dit dans le commentaire, j'ai maintenant, en fait, écrit un article de blog sur ce sujet, Les types de données intégrales de .NET et vous

52voto

hurst Points 1192

Selon la référence ci-dessous, le temps de fonctionnement optimise les performances de Int32 et les recommande pour les compteurs et autres opérations à accès fréquent.

Du livre : Kit de formation autonome MCTS (examen 70-536) : Microsoft® .NET Framework 2.0 - Fondation pour le développement d'applications

Chapitre 1 : "Les principes fondamentaux du cadre de travail".
Leçon 1 : "Utiliser les types de valeurs

Meilleures pratiques : Optimiser les performances avec les types intégrés

Le moteur d'exécution optimise les performances des types entiers 32 bits (Int32 et UInt32). Utilisez donc ces types pour les compteurs et autres variables intégrales à accès fréquent.

Pour les opérations en virgule flottante, Double est le type le plus efficace car ces opérations sont optimisées par le matériel.

En outre, le tableau 1-1 de la même section énumère les utilisations recommandées pour chaque type. Pertinent pour cette discussion :

  • Int16 - Interopération et autres utilisations spécialisées
  • Int32 - Nombres entiers et compteurs
  • Int64 - Grands nombres entiers

11voto

Curt Hagenlocher Points 12432

Int16 peut en fait être moins efficace car les instructions x86 pour l'accès aux mots prennent plus de place que les instructions pour l'accès aux mots. Cela dépendra de ce que fait le JIT. Mais quoi qu'il en soit, il est presque certain que ce ne sera pas le cas. plus efficace lorsqu'il est utilisé comme variable dans une itération.

9voto

Nils Pipenbrinck Points 41006

C'est le contraire qui est vrai.

Les entiers de 32 (ou 64) bits sont plus rapides que int16. En général, le type de données natif est le plus rapide.

Les Int16 sont intéressants si vous souhaitez alléger au maximum vos structures de données. Cela permet de gagner de l'espace et d'améliorer les performances.

3voto

Russ Points 1126

Toute différence de performance sera si minime sur le matériel moderne qu'à toutes fins utiles, elle ne fera aucune différence. Essayez d'écrire un couple de harnais de test et exécutez-les tous les deux quelques centaines de fois, prenez les temps moyens d'achèvement des boucles, et vous verrez ce que je veux dire.

Cela peut avoir un sens du point de vue du stockage si vous avez des ressources très limitées - systèmes embarqués avec une pile minuscule, protocoles filaires conçus pour des réseaux lents (par exemple GPRS, etc.), etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X