Effiziente Programme
-
Upload
erhard-dinhobl -
Category
Documents
-
view
61 -
download
4
description
Transcript of Effiziente Programme
Effiziente Programme
Performanceverbesserung
Erhard DinhoblMargit Weber
Martin ReitererStefan Reiterer
Agenda
Schritte zur Performance-Verbesserung:• Herausheben von Schleifeninvarianten• Caching / Memoziation• Binäre Suche• Memory Mapping der passwd Datei• Direct Memory Access (DMA)• Adressberechnungen vermeiden• Schreibeoperationen vermeiden
Resultierendes Programm Performancevergleich
Ursprünglich 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
Dateien öffnen im Normalfall sehr aufwändig! Datei nicht in jedem Schleifendurchgang neu öffnen
Problem:
Ursprünglich passwd Datei wurde bei jedem Aufruf von uid2name mittels I/O-Operationen durchsucht
Verbessert Beim 1. Aufruf:passwd Datei komplett einlesen, notwendige Informationen intern cachen und Datei wieder schließen
Ab 2. Aufruf:Ergebnis aus Cache (Liste, Array) zurückliefern.
Caching / Memoziation
I/O-Operationen sehr aufwändig! Datei bei ersten Aufruf von uid2name parsen und in Prozessspeicher chachen
Problem:
Binäre Suche
Problem: Lineare Suche in interner Datenstruktur (unsortiertes Array) ist sehr aufwändig. Lösungsvorschlag: Binäre 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 für "Ausreißer"
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 können nicht richtig einsortierte Elemente die gesamte Suche als ganzes in vielen Fällen 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 fällt 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 nächsten :
fach = atoi(map); //nach :x: ist UID map = len + 1; //nach UID positionieren filecn[fach] = old; //old zeigt auf UName
- Trotz Speicherverwendung sehr landsam: ~3.1 Mio Iterationen- Speicher von char-Pointern ebenfalls Verwalten- Gesamte Datei im Speicher (!!) mit strcpy realisieren, genauso langsam/schnell
Speicher von mmap() verwenden II
Ursprünglich linearer Suchaufwand zum Durchsuchen der gecachten Daten (Tuppel aus UID und Benutzername)
Verbessert • Stützung von Modulo-Algebra• Einordnung der gecachten Daten
in Equivalenzklassen (Kongruenz-Klassen)
• Lineare Suche innerhalb dieser Klassen
• 3K Klassen ~ DMA
Direct Memory-Access
Iterativer Suchaufwand von O(n2) Iterative Suche durch (direkten) Speicherzugriff ersetzen
Problem:
Adressberechnungen vermeiden
Problem: Da wir die passwd Datei in einer internen Datenstruktur (Array) verwalten, benötigen wir direkten Zugriff auf einzelne Arrayelemente.
Ursprünglich parsen der passwd Datei: Innerhalb einer while Schleife (siehe später) 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 können die meisten Compiler von selbst.
Schreibeoperationen vermeiden
Problem: Schreibeoperationen im Speicher sind sehr zeitaufwändig. strtok durch strchr und strncpy ersetzen
Ursprünglich strtok wurde zum parsen der passwd Datei verwendet: char *lname = strtok(line, ":");
strtok schreibt '\0' in den Speicher
Verbessert 1. strchr zur Positionierung im
Speicher verwendensearchstr = strchr(data, ':');
• strncpy zum Lesen von n Zeichen im Speicher verwendestrncpy(entry_ptr->name, data, searchstr - data);
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
Unsere Lösung
Caching / Memoziation der passwd Einträge Direkter Zugriff auf interne Datenstruktur (Pointer auf einfach verkettete Listen) Vermeidung von Schreibzugriffen auf den Speicher Verwendung eines Pools von Strukturelementen, anstatt malloc für jedes neue Strukturelement. (Listenerstellung) Nur Pointeroperation zum Parsen der passwd Datei