2010-07-22 3 views
2

J'ai une classe appelée "simulation" et une méthode de résolution de simulation.Performance de très grandes classes

class sim 
{ 
    void Step() 
    { 
    } 

    other methods (20+)... 
} 

La classe Sim est instanciée une seule fois pendant le programme.

La méthode Step est appelée de l'ordre de plusieurs millions au cours du programme.

La méthode Step utilise un grand nombre de variables locales (100+). Aucun de ces locaux n'est utilisé dans d'autres méthodes.

Vaut-il mieux faire de ces variables locales un membre de la classe ou les conserver comme locales dans Step() pour de meilleures performances?

+6

Je ne suis pas sûr de la performance, mais je m'inquiéterais de toute méthode qui aurait plus de 100 variables locales. Pour moi, cela donne une très forte indication que la méthode est susceptible d'être trop grande pour être facile à comprendre. –

+1

Cela ressemble à une optimisation prématurée. Faites des minutages pour voir si le programme passe plus de temps à «Step» que nécessaire. – ChrisF

Répondre

2

En règle générale, vous devez réduire la portée des variables et augmenter la portée uniquement si cela s'avère absolument nécessaire. La conversion des variables locales en variables membres est un choix de conception médiocre et nécessite donc une justification très forte.

Notez également que les variables locales ont un coût seulement si elles ont des constructeurs non triviaux. Une variable locale avec un constructeur noop ou aucun constructeur n'a aucun coût d'installation, il serait donc inutile d'étendre sa portée.

+0

J'utilise les doubles mais je les crée toujours chaque fois que je les appelle coûte beaucoup. L'augmentation des performances est très prometteuse avec la conversion des variables locales en variables membres dans mes tests. Mais le code est très moche et difficile à lire dans cet état actuel :( – Kayhano

+0

@Kayhano: Pourriez-vous s'il vous plaît expliquer comment créer des variables de pile "coûte beaucoup?" – Hut8

+0

@Kayhano: Vous n'étiez pas très clair sur la façon dont vous utilisez Je remarque dans votre commentaire à @Pontus Gagge que vous stockez et réutilisez des valeurs calculées sur plusieurs appels.Ce problème n'est pas un problème de pile-contre-membre, c'est un problème de mise en cache.Bien sûr, ce sera plus rapide si vous précalculez certaines valeurs et les mettez en cache à travers les appels, ce qui nécessite naturellement l'utilisation de variables non locales, mais cela n'a rien à voir avec le coût de création des variables de pile. –

4

Il depends. Quels types de variables: types primitifs ou objets? Si ce dernier, votre code IL va encore chasser leurs pointeurs. Si c'est le cas, cela dépend de l'ordre dans lequel vous y accédez et du processeur que vous ciblez. L'optimisation de la disposition des variables devrait venir assez loin dans la liste des activités de réglage des performances, en particulier en C# lorsque vous dépendez de l'assemblage dans lequel votre IL est traduite.

Comme d'habitude avec des optimisations: d'abord mesure performance pour identifier les goulots d'étranglement. Pensez ensuite à ce que vous pouvez faire pour les supprimer. Jusqu'à ce que vous sachiez que vous devez faire quelque chose comme ça, il suffit d'écrire votre code aussi clairement que possible: n'exposez pas inutilement les variables locales en les soulevant au niveau de la classe. Et envisager de diviser cette méthode Step(): une grande méthode est difficile à comprendre et donc encore plus difficile à optimiser.

+0

Toutes les variables locales sont des doubles. – Kayhano

+0

J'utilise des variables locales pour augmenter la vitesse. La plupart d'entre eux stockent des valeurs d'équation qui sont utilisées plusieurs fois. par exemple, // Calculer la distance de l'axe x. double dx = xp [i] - xp [j]; puis j'utilise dx dans plusieurs autres endroits. – Kayhano

0

Si certaines des variables contiennent des objets pouvant être réutilisés entre plusieurs appels de méthode, vous éviterez d'utiliser l'ancienne instance et de créer une nouvelle instance à chaque appel de méthode. Par exemple, les recherches dans un conteneur d'injection de dépendances qui ne changeront pas entre les appels de méthode pourraient être «mises en cache» dans un champ. En plus de cela, vous n'obtiendrez probablement pas beaucoup d'augmentation de performance. Vous pouvez essayer et utiliser un profileur pour mesurer les performances de votre code. Un profileur peut également vous aider à identifier d'autres goulots d'étranglement dans votre code.

Questions connexes