Schleifen und #define-Anweisungen im Performance Test

greggy80

Mitglied
Hallo!

Wer sehr tief in der C-Materie drin steckt und Ahnung von effizienter Programmierung hat, den bitte ich an dieser Stelle, weiterzulesen. Für alle anderen: es lohnt sich wahrscheinlich eher nicht :)

Ich arbeite an einem stream-basierten XML Parser, der auf Sensorknoten arbeiten soll. Für eine solche Applikation ist es sehr wichtig, dass sie sowohl resourcensparend hinsichtlich der Programmgröße als auch des während der Laufzeit verbrauchten Arbeitsspeichers ist und schnell läuft.

Als Vorbild habe ich mir Expat gegriffen. Expat schafft einen guten Durchsatz, aber leidet leider unter Platzverschwendung. In meiner Diplomarbeit soll ich nun herausfinden, in wie weit es möglich ist, einen XML Parser noch kleiner und vll. sogar schneller zu kriegen.

Eine erste Version des Parsers ist bereits fertig. Sie umfasst ca. 1000 Zeilen Programmcode (ist natürlich eingeschränkt in der Funktionalität, bspw. keine DTDs, keine Validierung, nur UTF-8) und arbeitet mit einem Puffer fester Größe (notwendig, da auf den Sensorknoten malloc und realloc mehr oder weniger verboten sind). Das Problem: sie ist nach Benchmarkmessungen im Schnitt 3x langsamer als Expat. Nun habe ich mich gefragt, warum das so ist. Auch Expat muss letzenendes jedes Zeichen aus der Eingabe einmal lesen und bewerten, schneller als O(n) geht also nicht.

Nachdem ich den Quellcode von Expat überflogen habe, ist mir aufgefallen, dass dort im Tokenizer nur minimal Schleifen verwendet werden (Feste Zeichenfolgen werden durch if- und switch-Anweisungen eingelesen) und viele Funktionen durch #define à la

Code:
#define fnc(s) switch (s){ case BLA : [...]}
während des Pre-Compiling durch direkten Code überschrieben. Das würde natürlich das Sichern des Stacks etc. sparen, da ja im Assember später kein "call" ausgeführt wird. Dennoch habe ich mir die Frage gestellt, ob dies der Grund sein kann, das mein Programm 3x langsamer läuft? Was meint ihr? Habt ihr vielleicht ein paar gute Artikel zu so einer Code-Optimierung?

Das Problem - mal angenommen, dies sei der Grund für die Effizienz - ist ja, dass sich der Quellcode aufbläht und sich somit die Effizienz antiproportional zur Programmgröße entwickelt. Das wäre für mich zwar nicht optimal, aber da ich in der Forschung arbeite, ok. Ich muss die Ineffizienz meines Programms nur irgendwie angemessen argumentieren können.

Ich bedanke mich schon mal für eure Antworten und Anregungen.

Beste Grüße, David
 
Hinzugefügt:

Ok, es hat sich etwas getan... ich Vollprofi habe den gcc im Debug Modus compilieren lassen, also ohne -O2 oder -O3. Jetzt läuft das Programm fast so schnell wie Expat, aber immer noch ein bißchen langsamer. Der Artikel ist damit nicht aufgehoben! :)
 
Hi.

Hast du denn mal den Code mit einem Profiler untersucht um herauszufinden wo die Flaschenhälse sind?

Es gibt noch mehr Optionen beim GCC die für die Optimierung zuständig sind. Z.B. -funroll-loops usw.

Gruß
 
Hm, kannst Du mir einen Profiler empfehlen (am besten Windows)?

Gibt es irgendwo eine Auflistung der Compiler-Direktiven zur Optimierung. Das Manual von gcc bringt mich irgendwie nicht weiter.
 
Zurück