Optimisations Génériques
Ici, comme certains de mes favoris optimisations. En fait, j'ai augmenté le temps d'exécution et la réduction du programme de tailles à l'aide de ces.
Déclarer des petites fonctions comme inline
ou macros
Chaque appel à une fonction (ou méthode) engage des frais généraux, tels que pousser les variables sur la pile. Certaines fonctions peuvent encourir des frais généraux sur le retour. L'inefficacité de la fonction ou de la méthode a de moins en moins de déclarations dans son contenu que les frais généraux. Ce sont de bons candidats pour l'in-lining, que ce soit en tant que #define
des macros ou inline
fonctions. (Oui, je sais, inline
n'est qu'une suggestion, mais dans ce cas, je considère cela comme un rappel pour le compilateur.)
Enlever les morts et code redondant
Si le code n'est pas utilisé ou ne contribue pas au programme du résultat, se débarrasser d'elle.
Simplifier la conception des algorithmes
Une fois, j'ai enlevé beaucoup de code assembleur et le temps d'exécution d'un programme en écrivant l'équation algébrique il était en train de calculer et ensuite simplifié l'expression algébrique. La mise en œuvre de la simplification d'expressions algébriques a pris moins de place et de temps que la fonction d'origine.
Déroulement De La Boucle
Chaque boucle a une surcharge de l'incrémentation et la résiliation de la vérification. Pour obtenir une estimation du facteur de performance, de compter le nombre d'instructions dans les frais généraux (minimum de 3: incrément, chèque, goto début de boucle) et diviser par le nombre d'instructions à l'intérieur de la boucle. Plus le nombre est bas mieux c'est.
Edit: fournir un exemple de déroulement de la boucle
Avant:
unsigned int sum = 0;
for (size_t i; i < BYTES_TO_CHECKSUM; ++i)
{
sum += *buffer++;
}
Après déroulement:
unsigned int sum = 0;
size_t i = 0;
**const size_t STATEMENTS_PER_LOOP = 8;**
for (i = 0; i < BYTES_TO_CHECKSUM; **i = i / STATEMENTS_PER_LOOP**)
{
sum += *buffer++; // 1
sum += *buffer++; // 2
sum += *buffer++; // 3
sum += *buffer++; // 4
sum += *buffer++; // 5
sum += *buffer++; // 6
sum += *buffer++; // 7
sum += *buffer++; // 8
}
// Handle the remainder:
for (; i < BYTES_TO_CHECKSUM; ++i)
{
sum += *buffer++;
}
Dans cet avantage, un avantage secondaire est gagné: plus les instructions sont exécutées avant que le processeur a pour recharger le cache d'instructions.
J'ai eu des résultats étonnants quand j'ai déroulé une boucle de 32 états. Ce fut l'un des goulots d'étranglement depuis que le programme a dû calculer une somme de contrôle sur un fichier de 2 go. Cette optimisation combinée avec bloc de lecture amélioration de la performance à partir de 1 heure à 5 minutes. Déroulement de la boucle fourni d'excellentes performances en langage d'assemblage, mon memcpy
a été beaucoup plus rapide que le compilateur memcpy
. -- T. M.
Réduction de if
des déclarations
Les processeurs de la haine des branches, ou des sauts, car il force le processeur à recharger sa file d'attente d'instructions.
Boolean Arithmétique (Édité: appliquer le code de format de fragment de code, ajout de l'exemple)
Convertir if
instructions booléennes affectations. Certains processeurs peuvent exécuter conditionnellement instructions sans ramification:
bool status = true;
status = status && /* first test */;
status = status && /* second test */;
Le court-circuitage de la Logique ET de l'opérateur (&&
) empêche l'exécution des tests si l' status
est false
.
Exemple:
struct Reader_Interface
{
virtual bool write(unsigned int value) = 0;
};
struct Rectangle
{
unsigned int origin_x;
unsigned int origin_y;
unsigned int height;
unsigned int width;
bool write(Reader_Interface * p_reader)
{
bool status = false;
if (p_reader)
{
status = p_reader->write(origin_x);
status = status && p_reader->write(origin_y);
status = status && p_reader->write(height);
status = status && p_reader->write(width);
}
return status;
};
Le facteur de Répartition Variable à l'extérieur des boucles de
Si une variable est créée à la volée à l'intérieur d'une boucle, déplacez la création et de répartition à l'avant de la boucle. Dans la plupart des cas, la variable n'a pas besoin d'être attribués lors de chaque itération.
Facteur d'expressions constantes à l'extérieur des boucles de
Si un calcul ou une valeur de la variable ne dépend pas de l'indice de boucle, le déplacer à l'extérieur (avant) de la boucle.
I/O dans les blocs
Lire et écrire des données dans les grands blocs (blocs). Plus le meilleur. Par exemple, la lecture d'un octect à un moment, c'est moins efficace que la lecture de 1024 octets à lire.
Exemple:
static const char Menu_Text[] = "\n"
"1) Print\n"
"2) Insert new customer\n"
"3) Destroy\n"
"4) Launch Nasal Demons\n"
"Enter selection: ";
static const size_t Menu_Text_Length = sizeof(Menu_Text) - sizeof('\0');
//...
std::cout.write(Menu_Text, Menu_Text_Length);
L'efficacité de cette technique peut être confirmé visuellement. :-)
Ne pas utiliser printf
de la famille constant de données
Constant de données peut être sortie à l'aide d'un bloc d'écriture. Formaté écrire des déchets d'analyse en temps le texte pour la mise en forme de caractères ou de traitement des commandes de mise en forme. Voir ci-dessus l'exemple de code.
Le Format de la mémoire, puis d'écrire
Format à un char
tableau à l'aide de plusieurs sprintf
, puis utilisez fwrite
. Cela permet également à la disposition de données pour être cassées en constant "sections" et la variable sections. Pense de publipostage.
Déclarer la constante de texte (chaîne de caractères littéraux) static const
Lorsque les variables sont déclarées sans le static
, certains compilateurs peuvent allouer de l'espace sur la pile et de copier les données à partir de la ROM. Ces deux opérations inutiles. Cela peut être résolu en utilisant l' static
préfixe.
Enfin, un Code comme le compilateur
Parfois, le compilateur peut optimiser plusieurs petits états de mieux qu'un compliqué que la version. Aussi, l'écriture de code pour aider le compilateur d'optimiser les aide aussi. Si je veux le compilateur à utiliser des bloc d'instructions de transfert, je vais écrire un code qui ressemble, il doit utiliser les instructions spéciales.