Sie sind auf Seite 1von 19

Effiziente Programme

Performanceverbesserung

Erhard Dinhobl Margit Weber Martin Reiterer Stefan Reiterer

Agenda
Schritte zur Performance-Verbesserung: Herausheben von Schleifeninvarianten Caching / Memoziation Binre Suche Memory Mapping der passwd Datei Direct Memory Access (DMA) Adressberechnungen vermeiden Schreibeoperationen vermeiden
Resultierendes Programm Performancevergleich

Herausheben von Schleifeninvarianten


Problem:

Dateien ffnen im Normalfall sehr aufwndig!


Datei nicht in jedem Schleifendurchgang neu ffnen

Ursprnglich
char *uid2name (int uid) { ... File *passwd = fopen(...); ... } int main () { ... while (...) { uid2name (...); } }

Verbessert
File *passwd;

char *uid2name (int uid) { ... } int main () { ... passwd = fopen (...); while (...) { uid2name (...); }
fclose (passwd);

Herausheben von Schleifeninvarianten

Caching / Memoziation
Problem:

I/O-Operationen sehr aufwndig!


Datei bei ersten Aufruf von uid2name parsen und in Prozessspeicher chachen Verbessert
Beim 1. Aufruf: passwd Datei komplett einlesen, notwendige Informationen intern cachen und Datei wieder schlieen Ab 2. Aufruf: Ergebnis aus Cache (Liste, Array) zurckliefern.

Ursprnglich
passwd Datei wurde bei jedem Aufruf von uid2name mittels I/OOperationen durchsucht

Caching / Memoziation

Binre Suche
Problem: Lineare Suche in interner Datenstruktur (unsortiertes Array) ist sehr aufwndig.

Lsungsvorschlag: Binre Suche in interner Datenstruktur.


Vorteil
Geringerer Suchaufwand, im Vergleich zu linearer Suche. Da passwd Datei "fast" sortiert ist, muss interne Datenstruktur nicht sortiert werden. Lineare Suche fr "Ausreier"

Nachteile
Sortierung der Datenstruktur notwendig (hoher Sortieraufwand). In unserem Fall war dies zwar nicht notwendig, konnten aber durch die Rechenoperationen (/2, etc.) nicht viel Rechenzeit gewinnen. Weiters knnen nicht richtig einsortierte Elemente die gesamte Suche als ganzes in vielen Fllen zunichte machen.

ffnen der Datei - mmap


Bisherige Version fopen() pro Zeile getline() Verbessert open() (char *) mmap() mmap() liefert Pointer auf char im Speicher, pro Zeile auslesen fllt weg.

Speicher von mmap() verwenden (while-body)


len = map; //aktuelle Pos. im Speicher while(*len != ':') len++; //bis zum ersten : in Zeile gehen old = map; //aktuelle Pos. speichern map = len + 1; //im Speicher bis nach : weitergehen
map += 2; //:x: berspringen len = map; //aktuelle Pos. nach :x: setzen while(*len != ':') len++; //weiter bis nchsten : fach = atoi(map); //nach :x: ist UID map = len + 1; //nach UID positionieren filecn[fach] = old; //old zeigt auf UName

Speicher von mmap() verwenden II


- Trotz Speicherverwendung sehr landsam: ~3.1 Mio Iterationen - Speicher von char-Pointern ebenfalls Verwalten - Gesamte Datei im Speicher (!!) mit strcpy realisieren, genauso langsam/schnell

Direct Memory-Access
Problem:

Iterativer Suchaufwand von O(n2) Iterative Suche durch (direkten) Speicherzugriff ersetzen

Ursprnglich
linearer Suchaufwand zum Durchsuchen der gecachten Daten (Tuppel aus UID und Benutzername)

Verbessert
Sttzung von Modulo-Algebra Einordnung der gecachten Daten in Equivalenzklassen (KongruenzKlassen) Lineare Suche innerhalb dieser Klassen 3K Klassen ~ DMA

mmap - Direct Memory-Access

Adressberechnungen vermeiden
Problem: Da wir die passwd Datei in einer internen Datenstruktur (Array) verwalten, bentigen wir direkten Zugriff auf einzelne Arrayelemente.
Ursprnglich
parsen der passwd Datei: Innerhalb einer while Schleife (siehe spter) wird auf Elemente des Arrays mittels Index zugegriffen:
entry[index].name = lname

Verbessert
Mittels Pointer auf die Datenstruktur (Array) zugreifen:
entry_ptr->name = lname

Spart Prozessor die Adressberechnung in jedem Schleifendurchgang. Anmerkung: Diese Optimierung knnen die meisten Compiler von selbst.

Schreibeoperationen vermeiden
Problem: Schreibeoperationen im Speicher sind sehr zeitaufwndig.
strtok durch strchr und strncpy ersetzen Ursprnglich
strtok wurde zum parsen der passwd Datei verwendet:
char *lname = strtok(line, ":");

Verbessert
1. strchr zur Positionierung im Speicher verwenden
searchstr = strchr(data, ':');

strncpy zum Lesen von n Zeichen im Speicher verwende


strncpy(entry_ptr->name, data, searchstr - data);

strtok schreibt '\0' in den Speicher

Schreibeoperationen vermeiden

strcpy/strncpy
char tmp[STR_SIZE] = {""}; char tmp2[STR_SIZE] = {""}; len = strchr(map, ':') - map; //UName finden strncpy(tmp2, map, len); //UName herauskopieren map += len + 1; //:x: berspringen map = strchr(map, ':') + 1; //:x: berspringen len = strchr(map, ':') - map; //UID finden strncpy(tmp, map, len); //UID herauskopieren fach = atoi(tmp); //UID konvertieren strcpy(filecn[fach], tmp2); //in HashTable speichern

Gegenberstellung der Optimierungen Zyklen

Gegenberstellung der Optimierungen Speicher

Unsere Lsung

Caching / Memoziation der passwd Eintrge


Direkter Zugriff auf interne Datenstruktur (Pointer auf einfach verkettete Listen) Vermeidung von Schreibzugriffen auf den Speicher Verwendung eines Pools von Strukturelementen, anstatt malloc fr jedes neue Strukturelement. (Listenerstellung) Nur Pointeroperation zum Parsen der passwd Datei