Ich entwickle eine C ++ - Anwendung (die in einer Linux-Box läuft), die sehr intensiv Protokolldateien liest und abgeleitete Ergebnisse auf Festplatte schreibt. Ich würde gerne wissen, welche die besten Praktiken für die Optimierung dieser Art von Anwendungen sind:
Gibt es eine gute Lektüre, wo ich die Grundlagen dafür bekommen könnte, um das vorhandene Know-how an mein Problem anzupassen?
Danke
Die Komprimierung kann sicherlich sehr hilfreich sein und ist viel einfacher als die Optimierung des Betriebssystems. Schauen Sie sich die gzip
und bzip2
Unterstützung in den Boost.IOStreams Bibliothek. Dies belastet jedoch den Prozessor.
Das Messen dieser Art von Jobs beginnt mit dem Befehl time
. Wenn die Systemzeit im Vergleich zur Benutzerzeit sehr hoch ist, verbringt Ihr Programm viel Zeit mit Systemaufrufen. Wenn die Wanduhrzeit ("echte" Zeit) im Vergleich zur System- und Benutzerzeit hoch ist, wartet sie auf die Festplatte oder das Netzwerk. Der top
-Befehl, der deutlich weniger als 100% CPU-Auslastung für das Programm anzeigt, ist ebenfalls ein Anzeichen für einen I / O-Engpass.
1) Überprüfen Sie die Sektorgröße Ihres Datenträgers.
2) Stellen Sie sicher, dass die Festplatte defragmentiert ist.
3) Lies Daten, die "lokal" sind, zu den letzten Lesevorgängen, die du gemacht hast, um die Cache-Lokalität zu verbessern (Cache wird vom Betriebssystem ausgeführt und viele Festplatten haben auch einen eingebauten Cache).
4) Daten zusammenhängend schreiben.
Bei der Schreibleistung werden Cache-Blöcke von Daten im Speicher, bis Sie ein Vielfaches der Sektorgröße erreichen, einen asynchronen Schreibvorgang auf die Festplatte initiieren. Überschreiben Sie nicht die Daten, die gerade geschrieben werden, bis Sie sicher sein können, dass die Daten geschrieben wurden (dh den Schreibvorgang synchronisieren). Doppel-oder Dreifach-Pufferung kann hier helfen.
Für die beste Leseleistung können Sie doppelte Lesevorgänge durchführen. Nehmen wir an, Sie cachen beim Lesen 16 KB Blöcke. Lesen Sie die 1. 16K von Diskette in Block 1. Leiten Sie ein asynchrones Lesen der 2. 16K in Block 2 ein. Beginnen Sie mit Block 1. Wenn Sie mit Block 1 fertig sind, synchronisieren Sie das Lesen von Block 2 und starten Sie ein asynchrones Lesen in Block 1 von der 3. 16K Block in Block 1. Arbeiten Sie nun mit Block 2. Wenn Sie das Lesen des 3. 16K Blockes synchronisiert haben, lösen Sie einen asynchronen Lesevorgang der 4. 16K in Block 2 aus und arbeiten Sie an Block 1. Spülen und wiederholen, bis Sie alle verarbeitet haben die Daten.
Wie schon gesagt, je weniger Daten Sie lesen müssen, desto weniger Zeit geht beim Lesen von der Festplatte verloren, so dass es sich lohnt, komprimierte Daten zu lesen und die CPU-Zeit auszugeben, um jeden Block beim Lesen zu erweitern. Wenn Sie den Block vor dem Schreiben ebenfalls komprimieren, sparen Sie Festplattenzeit. Ob dies ein Gewinn ist oder nicht, hängt davon ab, wie intensiv Ihre Verarbeitung der Daten ist.
Auch wenn die Verarbeitung auf den Blöcken asymmetrisch ist (dh Verarbeitungsblock 1 kann 3-mal so lange dauern wie Verarbeitungsblock 2), dann überlegen Sie sich, ob die Lesevorgänge dreifach oder mehr gepuffert sind.
Wie hier gesagt, sollten Sie die Größe des Blocks überprüfen. Sie tun dies mit stat family Funktionen. In struct stat befindet sich diese Information im Feld st_blksize.
Das zweite ist die Funktion posix_fadvise (), die dem Betriebssystem Hinweise zum Paging gibt. Sie sagen dem System, wie Sie die Datei (oder auch das Fragment einer Datei) verwenden wollen. Sie finden mehr auf der Handbuchseite.
Verwenden Sie bei Fenstern CreateFile () mit FILE_FLAG_SEQUENTIAL_SCAN und / oder FILE_FLAG_NO_BUFFERING anstelle von fopen () - zumindest zum Schreiben gibt dies sofort zurück, anstatt darauf zu warten, dass die Daten auf den Datenträger geleert werden.
Tags und Links c c++ performance io disk