2009-01-28 7 views
8

Je me demande quel genre de techniques d'optimisation les gens utilisent souvent de nos jours. J'ai vu des gens faire du cache tout le temps avec un dictionnaire et tout. Est-ce que l'espace de négociation pour la vitesse est la seule solution?Techniques d'optimisation en C#

+0

Pouvez-vous être plus précis sur le scénario que vous avez à l'esprit? "Optimisation" est une catégorie terriblement large. – Larsenal

+0

Oui, moyen de large. avez-vous une question spécifique? –

+0

Je me demandais simplement s'il était possible d'optimiser le code autrement qu'en utilisant la mise en cache avec les dictionnaires. – Tom

Répondre

2

Cela dépend de beaucoup de choses, vraiment. Par exemple, lorsque la mémoire devient un problème et que beaucoup d'objets temporaires sont créés, j'ai tendance à utiliser des pools d'objets. (Avoir un garbage-collector n'est pas une raison pour ne pas prendre en charge l'allocation de mémoire). Si la vitesse est ce qui compte alors je pourrais utiliser des pointeurs dangereux pour travailler avec des tableaux. De toute façon, si vous avez trop de mal avec les techniques d'optimisation dans une application C#/.net, vous avez probablement choisi la mauvaise langue/plate-forme.

1

En général, assurez-vous de comprendre la complexité temporelle des différents algorithmes et utilisez ces connaissances pour choisir judicieusement vos implémentations. Pour .NET en particulier, cet article explique en détail l'optimisation du code déployé sur le CLR (bien qu'il soit également pertinent pour Java ou toute autre plate-forme moderne), et est l'un des meilleurs guides que j'ai jamais lu :

http://msdn.microsoft.com/en-us/library/ms973852.aspx

Distillait l'article en une seule phrase: Rien n'affecte la vitesse d'une application .NET (avec des algorithmes sensibles) plus que la mémoire empreinte de ses objets. Faites très attention à minimiser votre consommation de mémoire.

4

Il y a aussi souvent des problèmes avec les algorithmes, généralement quand quelque chose de coûteux est fait à l'intérieur d'une boucle. Généralement, la première chose que vous faites est de profiler votre application, qui vous indiquera la partie la plus lente de l'application. Généralement, ce que vous faites pour accélérer votre application dépend de ce que vous trouvez. Par exemple, si votre application imite un système de fichiers, il se peut que vous appeliez la base de données de manière récursive pour remonter l'arborescence (par exemple). Vous pouvez optimiser ce cas en changeant ces appels récursifs en un appel de base de données aplati qui renvoie toutes les données d'un appel.

Encore une fois, la réponse est, comme toujours, «cela dépend». Cependant, plus d'exemples et de conseils peuvent être trouvés dans Rico Mariani's blog (parcourir quelques années, comme son accent a changé):

+0

Le profilage de votre application spécifique est probablement le seul bon conseil. Profil, voir ce qui est lent (ou mémoire hogging), et essayez de le réduire. – Kibbee

+0

Je suis actuellement à la recherche de bons exemples. Les gens utilisent memoization (mise en cache à nouveau) pour les récursions. +1 pour l'exemple de base de données. – Tom

3

Vraiment, il s'agit de votre choix dans les algorithmes. Habituellement, il n'y a pas de «solution miracle» pour l'optimisation. Par exemple, l'utilisation d'un StringBuilder au lieu d'une concaténation peut rendre votre code beaucoup plus rapide, mais il y a un compromis. Si vous ne concaténéz pas d'énormes ensembles de chaînes, la mémoire et le temps requis pour initialiser StringBuilder est pire que de simplement utiliser une concaténation régulière. Il y a beaucoup d'exemples de ceci dans tout le cadre, comme la mise en cache des dictionnaires, comme vous l'avez mentionné dans votre question. La seule optimisation générale que vous pouvez vraiment apprendre et appliquer à votre codage tout au long de votre journée est la performance de la boxe/unboxing (tas vs pile). Pour ce faire, vous devez apprendre de quoi il s'agit et comment éviter, ou réduire le besoin de le faire.

La documentation MSDN de Microsoft contient 2 articles sur les performances qui donnent de nombreuses bonnes techniques d'utilisation générale (ce ne sont en fait que des versions différentes du même article).

+0

StringBuilder est un optimiseur facile à implémenter lors de l'utilisation de la construction itérative. – Pat

1

je recommande Effective C# par Bill Wagner (first edition et second edition). Il passe en revue un certain nombre de constructions et de techniques du langage et explique lesquelles sont les plus rapides et pourquoi. Il touche également beaucoup de bonnes pratiques.

Plus souvent qu'autrement, l'optimisation de votre algorithme vous donnera des résultats bien meilleurs que n'importe quel type de langage/technique d'optimisation.

+0

Exactement ce que j'aurais dit - c'est là que j'irais sur mon premier passage. – mmr

2

Je proposerai ci-dessous

1. Quand utiliser StringBuilder

Vous devez avoir entendu avant qu'un objet StringBuilder est beaucoup plus rapide à cordes annexant ensemble que les types de chaînes normales.

The thing is StringBuilder is faster mostly with big strings. This means if you have a loop that will add to a single string for many iterations then a StringBuilder class is definitely much faster than a string type. However if you just want to append something to a string a single time then a StringBuilder class is overkill. A simple string type variable in this case improves on resources use and readability of the C# source code.

choisir simplement entre les objets correctement StringBuilder et les types de chaîne que vous pouvez optimiser votre code.

2. Comparaison des chaînes non sensibles à la casse

Dans une application parfois il est nécessaire de comparer deux variables de chaîne, sans tenir compte des cas. L'approche tentante et traditionnelle est de convertir les chaînes en minuscules ou majuscules et de les comparer, comme par exemple:

str1.ToLower() == str2.ToLower()

Cependant la fonction appeler à chaque fois ToLower() est un goulot d'étranglement dans performace. En utilisant à la place la fonction intégrée string.Compare(), vous pouvez augmenter la vitesse de vos applications.

Pour vérifier si deux chaînes sont égales en ignorant la casse ressemblerait à ceci:

string.Compare(str1, str2, true) == 0 //Ignoring cases

La fonction C# string.Compare retourne un entier qui est égal à 0 lorsque les deux chaînes sont égales.

3. Utilisez string.Empty

Ce n'est pas tant une amélioration de la performance car il est une amélioration de la lisibilité, mais il compte toujours que l'optimisation de code. Essayez de remplacer les lignes comme:

if (str == "")

avec:

if (str == string.Empty)

Ceci est tout simplement de meilleures pratiques de programmation et n'a pas d'impact négatif sur la performance.

Notez que la vérification de la longueur d'une chaîne est généralement plus rapide que la comparaison à une chaîne vide. Bien que cela puisse être vrai une fois que ce n'est plus une amélioration significative de la performance. Au lieu de coller avec la chaîne.Empty.

4. Remplacer ArrayList avec Liste <>

ArrayList sont utiles pour stocker plusieurs types d'objets dans la même liste. Toutefois, si vous conservez le même type de variables dans une ArrayList, vous pouvez augmenter les performances en utilisant à la place les objets List <.

Prenez ArrayList suivante:

ArrayList intList = new ArrayList(); 
intList.add(10); 
return (int)intList[0] + 20; 

avis qu'il ne contient que intergers. Utilisation de la liste <> classe est beaucoup mieux. Pour le convertir en une liste dactylographiée, seuls les types de variables doivent être changées:

List<int> intList = new List<int>(); 

intList.add(10) 

return intList[0] + 20; 

Il n'y a pas besoin de lancer des types avec Liste <>. L'augmentation des performances peut être particulièrement significative avec les types de données primitifs comme les entiers.

5. Utilisez & & et || opérateurs

Lors de la construction, si les déclarations, assurez-vous d'utiliser simplement le double et la notation (& &) et/ou la double ou la notation (||), (dans Visual Basic ils sont AndAlso et OrElse).

Si les instructions qui utilisent & et | doit vérifier chaque partie de la déclaration et ensuite appliquer le "et" ou "ou". D'autre part, & & et || Allez les déclarations une à la fois et arrêtez dès que la condition a été remplie ou non.

exécution moins de code est toujours un avantage de performace mais il peut également éviter les erreurs d'exécution, tenez compte code C#:

if (object1 != null && object1.runMethod()) 

Si object1 est nul, avec l'opérateur & &, object1.runMethod () ne s'exécutera pas. Si l'opérateur & & est remplacé par &, object1.runMethod() s'exécutera même si l'objet 1 est déjà connu comme étant null, provoquant une exception.

6. intelligent try-catch

déclarations Try-catch sont destinés à intercepter les exceptions qui échappent au contrôle des programmeurs, comme la connexion à Internet ou un dispositif par exemple. L'utilisation d'une instruction try pour conserver le code "simple" au lieu d'utiliser les instructions if pour éviter les appels sujets aux erreurs rend le code incroyablement plus lent. Restructurez votre code source pour exiger moins d'instructions try.

7. Remplacer divisions

C# est relativement lent en ce qui concerne les opérations de division. Une alternative consiste à remplacer les divisions par une opération de multiplication-décalage pour optimiser davantage C#.L'article explique en détail comment faire la conversion.

REFERENCE

Questions connexes