2010-07-02 7 views
1

est en dessous du code que je utiliseportée et la performance variable

private void TestFunction() 
{ 
    foreach (MySampleClass c in dictSampleClass) 
    { 
    String sText = c.VAR1 + c.VAR2 + c.VAR3 
    PerformSomeTask(sText,c.VAR4); 
    } 
} 

Mon ami a suggesed pour changer (pour améliorer les performances. dictSampleClass est un dictionnaire. Il a 10K objets)

private void TestFunction() 
{ 
    String sText=""; 
    foreach (MySampleClass c in dictSampleClass) 
    { 
    sText = c.VAR1 + c.VAR2 + c.VAR3 
    PerformSomeTask(sText,c.VAR4); 
    } 
} 

Ma question est, "Est-ce que le changement ci-dessus améliore les performances? Si oui, comment?"

WOW c'est plus que la réponse attendue. La plupart des gars ont dit "le compilateur C# s'en occuperait". Alors qu'en est-il c compilateur ??

+1

Je serais très surpris, si cette performance améliorée. Mais cela nuit à la lisibilité. – Henrik

+1

Il y a un HIT de performance (négligeable) lorsque vous affectez la chaîne vide uniquement pour réaffecter immédiatement dans le foreach. –

+1

Dupe: http://stackoverflow.com/questions/1884906/ –

Répondre

7

Le compilateur a l'intelligence de déplacer les déclarations variables dans/hors des boucles si nécessaire. Dans votre exemple, cependant, vous utilisez une chaîne, qui est immuable. En le déclarant à l'extérieur, je crois que vous essayez de «créer une fois, d'en utiliser plusieurs», mais les chaînes sont créées chaque fois qu'elles sont modifiées de sorte que vous ne pouvez pas y parvenir.

Ne pas sonner harse, mais c'est une optimisation prématurée, et probablement un échec - en raison de l'immutabilité des cordes.

Si la collection est volumineuse, parcourez le chemin d'ajout de nombreuses chaînes dans un StringBuilder - séparé par un délimiteur. Ensuite, divisez la chaîne sur ce délimiteur et parcourez le tableau pour les ajouter, au lieu de les concaténer et de les ajouter dans une boucle.

StringBuilder sb = new StringBuilder(); 

foreach (MySampleClass c in dictSampleClass) 
{ 
    sb.Append(c.VAR1); 
    sb.Append(c.VAR2); 
    sb.Append(c.VAR3); 
    sb.Append("|"); 
} 

string[] results = sb.ToString().Split('|'); 

for (int i = 0; i < dictSampleClass.Count; i++) 
{ 
    string s = results[i]; 
    MySampleClass c = dictSampleClass[i]; 
    PerformSomeTask(s,c.VAR4); 
} 

Je n'inclus aucun avantage à utiliser ce code - très probablement ne fonctionne même pas!

MISE À JOUR: à la lumière de la performance rapide de la création de chaînes de plusieurs chaînes, si PerformSomeTask est votre goulot d'étranglement, essayez de briser l'itération des chaînes dans plusieurs threads - il ne va pas améliorer l'efficacité du code, mais vous serez en mesure d'utiliser plusieurs cœurs.

+1

Je doute que cela améliore les performances – Manjoor

+0

Ditto réalise maintenant que l'initialisation d'une chaîne à partir de plusieurs chaînes est très rapide –

2

Exécutez les deux fonctions à travers le réflecteur et jetez un oeil à l'ensemble généré. Cela pourrait donner quelques idées, mais au mieux, l'amélioration de la performance serait minime.

0

Non, ce n'est pas le cas. Des choses comme celles-ci sont traitées par le compilateur C# qui est très intelligent et vous n'avez pas besoin de vous soucier de ces détails.

Utilise toujours un code qui favorise la lisibilité.

Vous pouvez vérifier cela en désassemblant le programme.

0

Ii n'améliorera pas les performances. Mais sur une autre note: les améliorations supposées sont sujettes aux erreurs. Vous devez mesurer votre application et optimiser uniquement la partie lente si nécessaire. Je ne crois pas que cette boucle soit le goulot d'étranglement de vos appliacations.

+0

On ne peut pas supposer que, soit 10k éléments avec des concaténations de chaînes dans un boucle serrée - pourrait avoir faim de mémoire –

+1

@Adam: Ce n'est pas vraiment une chaîne de concat Enation dans une boucle, c'est une initialisation de chaîne à partir de plusieurs sources. Ce n'est pas la même chose que 'String str = c.VAR1; str + = c.VAR2; str + = c.VAR3' ce qui causerait des problèmes de performance. – cjk

+0

@ck vrai, je n'ai jamais considéré les différences de performance de cela. –

1

Je vais pour cela à la place:

private void TestFunction() 
{ 
    foreach (MySampleClass c in dictSampleClass) 
    { 
    PerformSomeTask(c.VAR1 + c.VAR2 + c.VAR3, c.VAR4); 
    } 
} 

Il y a encore probablement aucun avantage réel de la performance, mais il supprime la création d'une variable que vous n'avez pas vraiment besoin.

+0

Hmmmm .. Mon objectif était seulement de connaître la différence et non l'optimisation du code. – Manjoor