![]() |
Kleiner Optimierungstest
Ich habe mir mal ein paar Gedanken über die Optimierung des Sourcecodes gemacht und dabei einige Tests angestellt. Hier die Resultate:
Test1:
Delphi-Quellcode:
gegen
if String = '' then
...
Delphi-Quellcode:
Resultat: Ersteres rund 1/3 schneller
if Length(String) > 0 then
... Test2:
Delphi-Quellcode:
gegen
if Control.Checked = True then
...
Delphi-Quellcode:
Resultat: Letzeres rund 1.3% schneller
if Control.Checked then
... Test3:
Delphi-Quellcode:
gegen
IntegerValue := Ord(True);
Delphi-Quellcode:
Resultat: Ersteres rund 7.3% schneller
IntegerValue := 1;
Test4:
Delphi-Quellcode:
gegen
BoolValue := Boolean(1);
Delphi-Quellcode:
Resultat: Ersteres rund 5.79% schneller
BoolValue := True;
Test5:
Delphi-Quellcode:
gegen
BoolValue := Not False;
Delphi-Quellcode:
Resultat: Ersteres rund 7% schneller
BoolValue := True;
Test6:
Delphi-Quellcode:
gegen
B := Not B;
Delphi-Quellcode:
Resultat: Ersteres rund 14.1% schneller
if B = True then
B := False else B := True; Nun, das finde ich ziemlich beeindruckend, testet es mal selbst. Solch ein Ergebnis hätte ich nicht gedacht. Vielleicht sind meine Messungen auch falsch. Ansonsten: Kennt ihr noch irgendwelche Optimierungsmethoden? EDIT: Getestet habe ich indem ich die zu testende Operation 5 sek. durchgeführ, das ganze 5 Mal wiederholt und dann den Durchschnitt gebildet habe. Gruß, Stefan |
Re: Kleiner Optimierungstest
@Stefan
Hey, nicht schlecht! Das hätte ich wirklich nicht gedacht. Wenn neue Test dazukommen, sei doch so nett und schreibe in der ersten Nachricht Deines Threads weiter! Falls Du magst, stelle doch Dein Testskelett zur Verfügung. Dann muss nicht jeder alles neu programmmieren. Ich werde in jedem Fall Deine Liste übernehmen. Optimierungen auf der Ebene dürften sich merklich auf die Programm Performance auswirken. Ganz Besonders in Schleifen. Super Sache! Ich bin auf die weitere Resultate gespannt. :hi: Go2EITS |
Re: Kleiner Optimierungstest
Zitat:
das kann eigentlich nicht sein! Wenn ich mir beide Zuweisunen im Debugger ansehe steht dort immer
Code:
Es wird also immer der selbe Code ausgeführt.
move eax, $00000001
Und bei Test 5 macht der Compiler in beiden Fällen daraus ein
Code:
Getestetet mit aktivierter Codeoptimierung.
move al, $01
|
Re: Kleiner Optimierungstest
Ohne jetzt dein Testprogramm als ganzes zu sehen und mit der Assembler-Aussage von Sharky sage ich jetzt einfach das du zwar schön gemessen hast aber deine Schlußfolgerung falsch ist. Sie muss (für einige der Tests) heißen:
Ein Multitaskingsystem wie Windows hat für gleiche triviale Aufgaben Laufzeitunterschiede von ca. x%. Wie wird die benötigte Rechenzeit (Laufzeit ist Aufgrund der fehlenden Echtzeitfähigkeit nicht Aussagekräftig) bestimmt? Mittels Uhrzeitabfrage ist Falsch. Du mußt eine bestimmte Aufgabe durchführen und am Anfang und Ende die Windows-Performancecounter abfragen. Damit bekommst Du eine bessere Aussage über die benötigte Rechenzeit. Auch sind die Prozentangaben (wenn denn wirklich unterschiedlicher Assemblercode rauskommt) Prozessorabhänig. Ein aktueller AMD-Prozessor benötigt für Realsierung X 5% weniger und ein Intel-Prozessor 3% mehr. Es gibt im Internet (URL im Moment nicht verfügbar) die sich mit Optimierungen für Delphi für diverse Prozessoren tiefer auseinandersetzt. Hier wird neben Mathematischen Funktionen wie sin/cos auch Stringoperationen optimiert. [EDIT] ![]() |
Re: Kleiner Optimierungstest
Hi,
nebst dass ich den beiden vorhergehenden Beiträgen einmal voll zustimmen möchte, wollte ich hier noch sagen, dass ich bei dir keine Optimierungen sehe. Ich meine klar, ist schon interessant zu sehen, dass deine Programme je nach Auslastung unterschiedliche Zeiten verbrauchen. Hier wäre es natürlich wichtig zu wissen wie viele Läufe mit jeder Konfiguration du gemacht hast und welche Optimierungen du aktiviert hast (oder ebend nicht). Aber viel wichtiger ist, es ist nichts optimiert. Wenn ich eine if-Abfrage um 2% schneller gestalten könnte (egal wie), von was für eine Anzahl von Takten sprechen wird denn dann bitte? Und wieviel Zeit ging da bisher verloren? Ich denke die wirklich aufwändigen Operationen finden doch woanders statt. Zudem stellt sich für mich die Frage, warum du hier die Verminderung von Rechenzeit mit Optimierung gleichsetzt. Optimaler Code sollte vorallem verständlich sein. Es ist wirklich eine der wichtigsten Eigenschaften von guten Code, dass er lesbar/wartbar/erweiterbar/... bleibt. Ob ich dabei 5% Geschwindigkeit auf der Strecke lasse ist letztlich egal. Das ist mit einer der vielen folgenden CPU-Generationen eh vergessen. Wahrscheinlicher ist sogar, dass die Compileroptimierung es eh besser weiß und wie in diesen Beispielen eh den gleichen Code erzeugt. Zudem läuft die Momentane Entwicklung auf Multithreading hinaus, du hast verschiedene Kerne und mehrere ALUs mit eigenen Pipelines. Hier wird sich kaum ein kleiner Unterschied in so einfachen Abfragen (deiner Beispiele) bemerkbar machen, als vielmehr das schreiben guter nebenläufiger Programme. Je nachdem wie gut du hier synchronisierst, sollte einiges mehr an Unterschied messbar sein und je nach CPU auch nochmal zwischen Single- und Multithreading. Gruß Der Unwissende |
Re: Kleiner Optimierungstest
Ich hätte nicht gedacht dass ich mit meinen Aussagen so sehr gegen eine Mauer fahre. Nun, man sagt ja: Wer einmal Blut geleckt hat...
@Der Unwissende: Natürlich hast du recht, der Code darf bei all seiner Optimiererei die Lesbarkeit nicht verlieren. Aber mich hatte es nunmal interessiert ob der Compiler nen Unterschied zwischen "if Control.Checked = True" oder "if Control.Checked" macht, vermutlich war meine Methodik, wie du schon meintest, dabei falsch. Ich habe einfach die Anzahl von Operationen pro Sekunde gemessen und dann verglichen und mich dabei darauf verlassen, dass die Werte vergleichbar sind. Gruß, Stefan |
Re: Kleiner Optimierungstest
Es ist ja nicht alles falsch:
Da ja Control.Checked vom Typ Boolean ist macht die 2. Variante
Delphi-Quellcode:
wenig Sinn.
if Control.Checked = True
|
Re: Kleiner Optimierungstest
Zitat:
Delphi-Quellcode:
Noch ein Wort zum "Str <> ''" vs. "Length(Str) > 0". Nicht nur das zweiteres mehr Tipparbeit ist, es enthält auch einen Funktionsaufruf, der immer Zeit kostet da die Prefetch-Queue des Prozessors neu aufgebaut werden muss. Das "Str <> ''" entspricht vom Code einem "Pointer(Str) <> nil".
var
b: Boolean; begin b := Boolean(-1); if b then ShowMessage('Wird angezeigt'); if b = True then ShowMessage('Solche Fehler sind später schwer zu finden. Ach ja, der Dialog wird _nicht_ angezeigt.'); end; Um noch eine Optimierung anzusprechen: Wenn man bei Parameters, die vom Typ String, Variant und dyn. Array sind, sollte man wenn möglich den "const" Operator benutzen. Dadurch erzeugt der Compiler keinen Extracode, der dafür sorgt, dass beim Eintritt in die Funktion der Referenzzähler des Parameters erhöht wird und beim Austritt (abgesichert durch ein try/finally) wieder heruntergezählt wird. |
Re: Kleiner Optimierungstest
Moin Stefan,
schau Dir das doch jeweils mal im CPU-Fenster an (jeweils Optimierung aktiviert)
Aus Test3 ersehe ich, dass bei Deinem Verfahren die Geschwindigkeitsdifferenzen zu messen, eine Abweichung von mindestens 7,3% keine Aussagekraft hat. |
Re: Kleiner Optimierungstest
@jbg
Delphi-Quellcode:
Die if b=TRUE Problematik war mir bis vor Kurzem nicht gekannt.
var
b: Boolean; begin b := Boolean(-1); if b then ShowMessage('Wird angezeigt'); if b = True then ShowMessage('Solche Fehler sind später schwer zu finden. Ach ja, der Dialog wird _nicht_ angezeigt.'); end; Ich verwende nur noch IF B Then so wie Du es obenstehend aufzeigst. @Der Unwissende Ich stimme Dir zu: 1.Code zuerst lesbar und wartbar. 2. "Fehlerfrei" 2. Dann nur Proceduren optimieren, die wirklich Performancegewinn bringen. 3. Und dann Entwicklung des Codes für Multithreading bei Bedarf. Da stellt sich für mich die Frage, ob eine Procedure, vorausgesetzt, sie wird oft aufgerufen, die lokalen Variablen, da sie ja jedes mal neu angelegt werden müssen, nicht besser global angelegt werden sollen, wie z. B. Procedure OFT(S:String); VAR Lokal:String; begin ... end; oder besser Procedure OFT; begin S:=... //Zuweisung/Verarbeitung String:= //Zuweisung end; oder der besser Übersichtlichkeit und Wartung lokal verarbeitet werden. Dabei habe ich keine Ahnung, ob die untere Version performancemäßig, wirklich etwas bringt. Wirklich bringt meines Ermessens nach unnötige Funtionsaufrufe wie: // Die schlechte Version for I:=1 to length(String).. statt // Die gute Version s:=String; for i:=1 to S ... Was mein Ihr? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz