Codeoptimierung — Änderungen 7112 → 7116

Zeile 1: Zeile 1:
 
Durch die Optimierung des Quellcodes eines Programms kann dieses schneller, effektiver und platzsparender arbeiten.
 
Durch die Optimierung des Quellcodes eines Programms kann dieses schneller, effektiver und platzsparender arbeiten.
 +
 
== Allgemeines ==
 
== Allgemeines ==
 
=== Datengrößen ===
 
=== Datengrößen ===
−
Die Wortgröße des Prozessors zu verwenden ist oft besser als dies nicht zu tun (32 Bit bei i386, 64 Bit bei x86-64).
+
*Die Wortgröße des Prozessors zu verwenden ist meist die schnellste. (32 Bit bei i386, 64 Bit bei x86-64).
  
 
=== Alignment ===
 
=== Alignment ===
 +
* Code und Daten sollten in getrennten [[Page]]s 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)
 +
 +
=== 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 ==
 
== Assembler ==
−
 
 
=== Reduzierung der Codegröße ===
 
=== Reduzierung der Codegröße ===
−
Die nachfolgenden Tricks eignen sich besonders zum Programmieren in [[Assembler]], wie es z. B. im [[Bootloader]] nötig ist.
+
Die nachfolgenden Tricks eignen sich besonders zum Programmieren in [[Assembler]], wie es z.B. im [[Bootloader]] nötig ist.
  
 
{| {{prettytable}}
 
{| {{prettytable}}
Zeile 19: Zeile 45:
 
|-
 
|-
 
|Prüfen, ob Register 0 ist
 
|Prüfen, ob Register 0 ist
−
|<asm>test eax, eax
+
|<asm>test eax, eax<br>jz ...</asm>
−
jz ...</asm>
 
 
|-
 
|-
 
|Multiplikation mit einer Zweierpotenz
 
|Multiplikation mit einer Zweierpotenz
−
|<asm>shl eax, log<sub>2</sub>Faktor</asm>
+
|<asm>shl eax, log2 Faktor</asm>
 
|-
 
|-
 
|Division durch eine Zweierpotenz
 
|Division durch eine Zweierpotenz
−
|<asm>shr eax, log<sub>2</sub>Divisor</asm>
+
|<asm>shr eax, log2 Divisor</asm>
 
|-
 
|-
 
|Beliebige Multiplikation
 
|Beliebige Multiplikation
Zeile 33: Zeile 58:
 
|Schleife
 
|Schleife
 
|<asm>mov ecx, [Anzahl_Wiederholungen]
 
|<asm>mov ecx, [Anzahl_Wiederholungen]
−
von_vorn:
+
von_vorne:
−
; ...
+
...
−
loop von_vorn</asm>
+
loop von_vorne</asm>
 +
|-
 +
|Bedingte Wertzuweisung, Register
 +
|<asm>cmov?? eax, [Wert]</asm>
 +
|-
 +
|Bedingte Wertzuweisung, Byte im Arbeitsspeicher
 +
|<asm>set?? [Wert]</asm>
 +
|-
 +
|Addition, Subtraktion
 +
|<asm>lea eax, [ebx + ecx + 4]</asm>
 
|}
 
|}
  
 
=== Steigerung der Effektivität ===
 
=== Steigerung der Effektivität ===
 +
* Registerzugriffe sind immer schneller als Arbeitsspeicher-Zugriffe.
 +
* Daher sollten Parameter an Funktionen über Register, nicht über den Stack übergeben werden.
 +
 
==== PUSHA / POPA ====
 
==== PUSHA / POPA ====
−
Ist es schneller jedes Register einzeln zu pushen, oder besser pusha?
+
* 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 ==
 
== Hochsprachen ==
 +
=== Codeoptimierung durch Compiler ===
 +
TODO
 
=== Optimierungstools ===
 
=== Optimierungstools ===
−
TODO
+
''Bisher keine Vorschläge''
 +
 
  
 
== siehe auch ==
 
== siehe auch ==
Zeile 50: Zeile 90:
  
 
== Weblinks ==
 
== Weblinks ==
−
*[http://www.intel.com/Assets/PDF/manual/248966.pdf Intel ‐ Optimierung für IA32]
+
*[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]  
+
*[http://support.amd.com/us/Processor_TechDocs/25112.PDF AMD - Software Optimierung für AMD64]
  
 
[[Kategorie:Stub]]
 
[[Kategorie:Stub]]
 +
[[Kategorie:x86]]