Durch die Optimierung des Quellcodes eines Programms kann dieses schneller, effektiver und platzsparender arbeiten. == Allgemeines == === Datengrößen === *Die Wortgröße des Prozessors zu verwenden ist meist vorteilhaft. (32 Bit bei i386, 64 Bit bei x86-64). === Alignment === * Code und Daten sollten in getrennten [[Paging|Pages]] gehalten werden. * Wenn man aber gezwungen ist, Code und Daten zu mischen, dann sollte man die Daten so legen, dass Sprünge nicht darüber hinweg springen müssen. * Selbst modifizierender Code widerspricht diesem Prinzip. * Sprungziele sollten am Anfang eines Paragrafs (16Byte) stehen. * Die CPU hat einen internen Datencache von 64KB. Daten, die über eine 64KB Grenze verteilt sind, müssen dann zweimal gecacht werden, was die Performance mindert. Somit sollten Daten ihrer Größe entsprechen ausgerichtet werden, also z.B. DWORDs auch nur am Anfang der 4 Byte Grenzen. * Ebenso sollte der [[Stack]] 64KB aligned sein, und die Größe seiner Elemente gleich bleiben. === Sprünge und Schleifen === Sprünge sind ein Problem für die CPU, weil sie das cachen des Codes erheblich erschweren. * Sprünge sollten vermieden werden, wann immer dies möglich ist * Unnötige Sprünge können vermieden werden, indem der wahrscheinlichere Zweig in einer Verzweigung (if/switch) zuerst ausgeführt wird. Somit sind auch Schleifen performancekritisch, da in ihnen sehr oft gesprungen wird. * Schleifen sollten, wenn möglich, aufgelöst werden. * Bei verschachtelten Schleifen sollte diejenige innen stehen, die am längsten läuft. * Wenn in einer Schleife dieselbe Berechnung immer wieder ausgeführt wird, dann kann diese auch einmalig vor der Schleife berechnet werden. Auch Funktionsaufrufe fallen unter Sprünge. * Funktionen, die nur wenig leisten, sollten vermieden und ihr Code direkt eingearbeitet werden (diesem Zweck dient das inline-Schlüsselwort in C, allerdings werden kurze Funktionen bei entsprechender Optimierung vom C-Compiler oft auch automatisch entsprechend behandelt) === Caching === * Je weniger Sprünge, desto effektiver kann der Code gecacht werden. * Die CPU kann bis zu 16 verschachtelte Funktionsaufrufe cachen, mehr als 16 Verschachtelungen verringern die Performance. * Die CPU kann Befehle am besten cachen, die weniger als 8 Byte lang sind. Außerdem sollten dabei WORD-Konstanten vermieden werden. Komplexe Befehle wie sysenter oder leave * Alignments sollten immer eingehalten werden! == Assembler == === Reduzierung der Codegröße === Die nachfolgenden Tricks eignen sich besonders zum Programmieren in [[Assembler]], wie es z. B. im [[Bootloader]] nötig ist. {| {{prettytable}} !Beschreibung !Optimierter Code |- |Register 0 setzen |xor eax, eax |- |Prüfen, ob Register 0 ist |test eax, eax jz ... |- |Multiplikation mit einer Zweierpotenz |shl eax, log2 Faktor |- |Division durch eine Zweierpotenz |shr eax, log2 Divisor |- |Beliebige Multiplikation |imul eax, [Faktor_1], [Faktor_2] |- |Schleife |mov ecx, [Anzahl_Wiederholungen] von_vorne: ... loop von_vorne |- |Bedingte Wertzuweisung, Register |cmov?? eax, [Wert] |- |Bedingte Wertzuweisung, Byte im Arbeitsspeicher |set?? [Wert] |- |Addition, Subtraktion |lea eax, [ebx + ecx + 4] |- |Bestimmte Multiplikationen (z. B. mit 3 oder 5) |lea eax, [edx * 4 + edx] |} === Steigerung der Effektivität === * Registerzugriffe sind immer schneller als Arbeitsspeicherzugriffe. * Daher sollten Parameter an Funktionen über Register, nicht über den Stack übergeben werden. ==== PUSHA / POPA ==== * Von der Verwendung von pusha/popa ist meist abzuraten, da man auch jedes einzelne Register direkt pushen/popen kann, und dabei selektiver vorgehen kann. == Hochsprachen == === Codeoptimierung durch Compiler === Der [[GCC | gcc]] übernimmt die Optimierung über einen dieser Befehle: * -Ox (x ist der Grad der Optimierung; 3 ist die höchste Stufe) * -Os (s ist keine Variable, sondern wird genau so gesetzt!) '-Os' veranlasst den Compiler, nicht unbedingt performanten Code, aber auf jeden Fall kleine Programme zu erzeugen („size optimisation“). 'Ox' dagegen führt dazu, dass verschiedene Optimierungen zur Geschwindigkeitsverbesserung eingeschaltet werden. '-O3' ist die höchste Stufe, führt aber bei einigen Programmen zu Problemen (z. B. empfiehlt Gentoo, -O2 und nicht -O3 zum Kompilieren des Systems zu nutzen). Das sollte jeder für seine Software selbst ausprobieren. Übrigens kann man mit NASM die Codeoptimierung mit '-Ox' (hier ist x keine Variable!) einschalten. Dies ist jedoch nicht nötig, da das Flag standardmäßig aktiviert ist. Jedoch bleibt NASM ein Assembler, und so ist es dennoch sehr wichtig, die oben beschriebenen Optimierungsvorschläge auch zu nutzen. === Optimierungstools === ''Bisher keine Vorschläge'' == siehe auch == * [[Ausgabe_8#Tipps_.26_Tricks|Ausgabe 8]] == Weblinks == *[http://www.intel.com/Assets/PDF/manual/248966.pdf Intel - Optimierung für IA32] (Kapitel 3.3 bis 3.9 sind empfehlenswert) *[http://support.amd.com/us/Processor_TechDocs/25112.PDF AMD - Software Optimierung für AMD64] [[Kategorie:Stub]] [[Kategorie:x86]] [[en:Optimizing]]