Für die Lesbarkeit ist dies natürlich eine Katastrophe biblischen
Ausmaßes. In einer bestimmten Klasse sieht das durchgehend so schlimm
aus.
Ich könnte natürlich erst mal auf die relevanten Stellen Pointen, aber
wie schaut es da mit dem Tempo aus? Im Debugbuild wird das wohl alles so
wie es ist kompiliert. Wie schaut es da aber im Releasebuild mit -03
aus? Mir ist das Tempo an dieser Stelle wichtiger als die Lesbarkeit.
Dann bleibt auch noch die Möglichkeit zusätzliche Methoden aufzurufen um
alles sich Wiederholende da reinzupacken. Zusammen mit den Pointern wäre
das für mich die optimalste Lösung, WENN das Tempo darunter nicht leidet
(wie gesagt, im Releasebuild). Aber werden Funktionsmethoden überhaupt
optimiert?
Also im Prinzip: Ist es möglich die Lesbarkeit zu verbessern, ohne, dass
das Tempo darunter leidet? Falls ja, worauf muss geachtet werden?
Vielen lieben Dank schonmal :)
Grüße
Reggie
Edit: achso, gcc 5.3.0 und läuft auf einem stm32
ist jetzt zwar C++, aber sollte ich C auch kein Problem sein. Das ist
zumindest besser lesbar. Langsamer ist es auf jeden Fall auch nicht. Ob
es schneller ist hängt vom Compiler ab.
Peter II schrieb:> Auto xx StringReq::Char::Paint& StringReq::Char::Paint;Peter II schrieb:> Langsamer ist es auf jeden Fall auch nicht.
Ist es nicht so, dass während des Programmablaufs erst jedes mal xx
initialisiert wird?
Reginald L. schrieb:> Ist es nicht so, dass während des Programmablaufs erst jedes mal xx> initialisiert wird?
ja und nein. Der wert wird in ein Register gespeichert, das muss der
Compiler aber sowieso machen. Im schlimmsten fall macht er es bei deiner
Version 6mal (wenn nicht genügend Register frei sind).
Wenn der Compiler der Meinung ist, das er xx gar nicht braucht kann er
es ja immer noch wegoptimieren.
Wenn du dir nicht sicher bist, dann musst du im ASM code nachschauen.
Peter II schrieb:> ja und nein. Der wert wird in ein Register gespeichert, das muss der> Compiler aber sowieso machen. Im schlimmsten fall macht er es bei deiner> Version 6mal (wenn nicht genügend Register frei sind).
Es bleibt einem aber auch nichts erspart, da muss ich mich wohl in die
Materie einlesen :>
Peter II schrieb:> dann musst du im ASM code nachschauen.
Hehe, dachte ich mir schon, dass es darauf hinausläuft.
Vielen Dank erstmal, ich schließe daraus: Ich muss lernen wie die CPU
arbeitet :>
Reginald L. schrieb:> Vielen Dank erstmal, ich schließe daraus: Ich muss lernen wie die CPU> arbeitet :>
nein, die Frage ist wie schlau der Compiler ist.
Ich habe bis jetzt immer gute Erfahrung mit Referenzen bei solchen
Konstukten gemacht, manchmal stellen sich die Compiler sonst zu dumm an.
Moin,
Sind das alles etwa namespaces oder hast du Schlingel einen Haufen
statische Methoden?
Für die Lesbarkeit müsstest du ein wenig mehr Posten. Meistens ist es
kein einzelner Abschnitt, den man nur verbessern muss, sondern es ist
etwas mehr rework fällig.
Beschreiben doch mal den Projekt etwas genauer. Also nur den Teil, mit
dem du zeichnen möchtest. Dann ist es auch einfacher einen sinnvollen
Tip abzugeben.
Grüße
Peter II schrieb:> ein, die Frage ist wie schlau der Compiler ist.
Für die paar einfachen Berechnungen ist der allemal schlau genug.
Um den Quelltext lesbarer zu machen, könnte das "using"-Keyword helfen.
Oliver
Reginald L. schrieb:> Also im Prinzip: Ist es möglich die Lesbarkeit zu verbessern, ohne, dass> das Tempo darunter leidet?
Ausprobieren! Optimieren bedeutet: Code ändern. Code möchtest Du aber
nur ändern, wenn er lesbar ist und damit die Änderungen nachvollziehbar
sind und die Gefahr, dass etwas kaput geht minimal ist (im Idealfall
hast Du Unit-Tests, die nahelegen, dass nix kaput gegangen ist).
Fang mit lesbarem und korrekten Code an (und nein, lesbar bedeutet nicht
naive). Dann misst Du einfach mit einem Profiler, optimierst und misst
wieder mit dem Profiler. Fertig!
Die Mikro-Optimierungen, über die Du Dir hier Gedanken machst, bekommen
die Compiler alle von alleine hin. (Interessanter Talk zum Thema auf der
Metting C++ 2015 ("Understanding Compiler Optimization"):
https://www.youtube.com/watch?v=FnGCDLhaxKU)
Oliver S. schrieb:> Für die paar einfachen Berechnungen ist der allemal schlau genug.
leider nicht. Genau bei solchen code wie oben, habe ich schon oft erlebt
das er die Offset von den Objekten jedes mal neu berechnet.
Torsten R. schrieb:> Dann misst Du einfach mit einem Profiler, optimierst und misst> wieder mit dem Profiler. Fertig!
halte ich für eine schlechte Idee. Der Profiler sagt mir nicht wo sich
der Compiler eventuell etwas dumm anstellt. Das sieht man aber recht
schnell im ASM code.
Leider fehlen wirklich ein paar Infos. Niemand weis ob das alle Static
ist oder zu Laufzeit erzeugt wurde.
nicht“Gast„ schrieb:> Sind das alles etwa namespaces oder hast du Schlingel einen Haufen> statische Methoden?
Sowie als auch :)
nicht“Gast„ schrieb:> Für die Lesbarkeit müsstest du ein wenig mehr Posten.
Besser nicht, sonst wird der Thread nur geflamed ;)
nicht“Gast„ schrieb:> Beschreiben doch mal den Projekt etwas genauer.
Es werden statische Buffer befüllt. Die werden später von der
GUI-Messageloop ausgelesen.
Ja, ich weiß, das sieht furchtbar aus :) Auf die Schnelle ist mir
gestern nichts Besseres eingefallen :>
Bisher mache ich es so, dass ich alle Objekte die während des gesamten
Programms nur eine Instanz (ist ja dann eigentlich keine) benötigen, auf
static setze.
Peter II schrieb:> halte ich für eine schlechte Idee. Der Profiler sagt mir nicht wo sich> der Compiler eventuell etwas dumm anstellt. Das sieht man aber recht> schnell im ASM code.
Wenn Du wirklich C++ code hast, und den optimierst, dann wirst Du kaum
noch den Quellcode mit dem Assembler zusammen bekommen.
Torsten R. schrieb:> Die Mikro-Optimierungen, über die Du Dir hier Gedanken machst, bekommen> die Compiler alle von alleine hin.
Muss in eine Funktion nicht erst "reingesprungen" werden? also kommt da
nicht eine zusätzliche Instruktion für die CPU hinzu? Genauso wie für
die Variableninitialisierung?
Reginald L. schrieb:> Bisher mache ich es so, dass ich alle Objekte die während des gesamten> Programms nur eine Instanz (ist ja dann eigentlich keine) benötigen, auf> static setze.
Und warum machst Du das?
Torsten R. schrieb:> Wenn Du wirklich C++ code hast, und den optimierst, dann wirst Du kaum> noch den Quellcode mit dem Assembler zusammen bekommen.
Wenn ich bei mir Disassemble zeigt er mir aber an in welcher Stelle im
Quellcode ich gerade (ungefähr) bin.
Torsten R. schrieb:> Und warum machst Du das?
Gute Frage, nächste bitte.
Daran habe ich mich zu Anfang gewöhnt, weil ich in die ISRs nur statics
mitnehmen konnte. Irgendwas war da mal. Wobei auf meiner Liste steht,
dass ich die ISRs zukünftig in die Klassen mit reinpacken wollte, habe
mich dazu aber noch nicht genug eingelesen.
Reginald L. schrieb:> static uint8_t R_bg[GUI_MAX_STRING_QUEUE_OBJECTS];
warum nicht noch eine RGB struct?
also eine Array auf R G B . Dann würde es logischer sein und sich noch
etwas mehr optimieren lassen.
Das R G B in 3 verschiedenen Arrays halte ich für nicht schlau.
Peter II schrieb:> warum nicht noch eine RGB struct?
Danke für den Tipp, logisch!
Ich pack jetzt mal einen Sack pointer und Funktionen aus und schau mir
das im disassembler mal an was sich da tut.
Reginald L. schrieb:> Muss in eine Funktion nicht erst "reingesprungen" werden? also kommt da> nicht eine zusätzliche Instruktion für die CPU hinzu? Genauso wie für> die Variableninitialisierung?
Spannend: Du machst nicht den Eindruck, zu wissen, was ein Compiler kann
oder nicht kann, bist aber der Meinung, dem Compiler in jeder Zeile Code
unter die Arme greifen zu müssen ;-)
Sehr ernst gemeint: Schreib korrekten_ und _lesbaren Code. Wenn der
Code dann macht, was er soll, dann suchst Du die 5% Code bei denen es
wirklich wichtig ist, dass der schnell ist und optimierst ihn. Und das
machst Du auch nur dann, wenn Du feststellst, dass der Code wirklich zu
langsam ist.
Ich arbeite schon seit 20 Jahren als Software-Entwickler und habe vor'm
Profiling natürlich auch immer eine Vermutung, welcher Teil einer
Software am besten zu optimieren wäre, ich liege aber eigentlich immer
falsch.
Berufsanfänger überschätzen (fast) immer die Notwendigkeit von
Performance. Korrektheit ist immer wichtiger und Lesbarkeit ist fast
immer wichtiger.
Je schneller Du zu einer korrekten und lesbaren Software kommst, um so
mehr Zeit bleibt Dir für's Optimieren.
mfg Torsten
P.S.: Zeitlos richtig: "premature optimization is the root of all evil"
Knuth,
http://web.archive.org/web/20130731202547/http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf
Torsten R. schrieb:> Spannend: Du machst nicht den Eindruck, zu wissen, was ein Compiler kann> oder nicht kann, bist aber der Meinung, dem Compiler in jeder Zeile Code> unter die Arme greifen zu müssen ;-)
Hab ich auch niemals behauptet, programmiere auch noch nicht so lang.
Torsten R. schrieb:> Sehr ernst gemeint: Schreib korrekten_ und _lesbaren Code. Wenn der> Code dann macht, was er soll, dann suchst Du die 5% Code bei denen es> wirklich wichtig ist, dass der schnell ist und optimierst ihn. Und das> machst Du auch nur dann, wenn Du feststellst, dass der Code wirklich zu> langsam ist.
Das ist mal ne Ansage! Mach ich ab jetzt mal so. Ich merke schon, dass
ich ziemlich viel Zeit ins Nachgrübeln investiere: "Wie mache ich das
jetzt am besten, damit das fix abgearbeitet wird?"
Torsten R. schrieb:> Berufsanfänger
Ich bin ein Hobbyanfänger :)
Ich hab das auch schon öfter erlebt, daß sich der Compiler bei
mehrfachen Indirektionen immer wieder neu nen Wolf rechnet.
Dann kann man ihm mit einem Pointer auf die Sprünge helfen.
So ein Pointer macht auch den Code viel lesbarer, weil sich auch der
Leser dann nicht bei jeder Variable mühsam durch alle Indirektionen
durchhangeln muß.
Wenn man viele ähnliche Sachen durch Zusammenfassen verkürzen kann, wird
oft auch der Code kleiner und schneller.
Peter D. schrieb:> Ich hab das auch schon öfter erlebt, daß sich der Compiler bei> mehrfachen Indirektionen immer wieder neu nen Wolf rechnet.> Dann kann man ihm mit einem Pointer auf die Sprünge helfen.
Zuvor fängt man doch mit den Grundlagen an. Statt ein struct von Feldern
zum Beispiel ein Feld mit einem struct nehmen. Duplizierte
Datenstrukturen (RGB oder die struct-Teile mit FrameBuffer, xStart,
yStart, Width, Height, Brush, Color) in eigene Datenstrukturen packen
(Neudeutsch refactoring). Die hinrnrissige Verschachtelung auflösen
(notfalls mit inline Accessoren und Manipulator-Methoden,
Operator-Overloading (Hilfe!), und/oder using).
Hab jetzt das ganze mal etwas anders aufgebaut, zusätzliche Klassen
erzeugt für RGB, die auch mit Übergabeparametern die Berechnung
vornimmt, das von vorhin sieht jetzt so aus:
Zumindest augenscheinlich sind weniger Zeilen im Dissasembler zu sehen,
bis der Rücksprung erfolgt. Heißt das jetzt, dass er besser optimiert
hat als ich, oder? :)