Frage

ich mit sehr großen Textdateien (2 GBs) zu tun haben, ist es zwingend notwendig, sie Zeile für Zeile zu lesen / schreiben. Um 23 Millionen Zeilen zu schreiben ofstream mit wirklich so langsam ist, am Anfang habe ich versucht, den Prozess zu schreiben, große Teile von Linien in einem Speicherpuffer zu beschleunigen (zum Beispiel 256 MB oder 512 MB) und schreiben Sie dann den Puffer in die Datei . Das hat nicht funktioniert, die Leistung ist mehr oder weniger gleich. Ich habe das gleiche Problem, die Dateien zu lesen. Ich weiß, dass die I / O-Operationen durch das STL-I / O-System gepuffert werden, und dies hängt auch von dem Plattenplaner Politik (vom Betriebssystem verwaltet, in meinem Fall Linux).

Jede Idee, wie die Leistung zu verbessern?

PS: Ich habe darüber nachgedacht, einen Hintergrund Kind-Prozess (oder einen Thread) mit Hilfe der Datenblöcke zu lesen / schreiben, während die Programmdaten verarbeitet, aber ich weiß nicht (vor allem im Fall der Subprozess), wenn dieser Wille würdig sein.

War es hilfreich?

Lösung

Eine 2GB-Datei ist ziemlich groß, und Sie müssen alle möglichen Bereiche zu beachten, die als Engpässe wirken können:

  • Die Festplatte selbst
  • Die HDD-Schnittstelle (IDE / SATA / RAID / USB?)
  • Betriebssystem / Dateisystem
  • C / C ++ Bibliothek
  • Ihr Code

ich, indem Sie einige Messungen beginnen würde:

  • Wie lange dauert Code nehmen zu lesen / schreiben 2GB-Datei,
  • Wie schnell kann die ' dd ' Befehl lesen und schreiben auf die Festplatte? Beispiel ...

    dd if=/dev/zero bs=1024 count=2000000 of=file_2GB

  • Wie lange dauert es, schreiben / lesen gerade groß fwrite mit () / fread () ruft

Ihre Festplatte Unter der Annahme der Lage ist, das Lesen / Schreiben bei etwa 40MB / s (was wahrscheinlich eine realistische Zahl ist von starten), Ihre 2GB Datei nicht schneller laufen kann als etwa 50 Sekunden.

Wie lange ist es eigentlich zu nehmen?

  

Hallo Roddy, mit fstream Leseverfahren   mit 1,1 GB Dateien und großen   Puffer (128.255 oder 512 MB) dauert es   etwa 43-48 Sekunden und es ist die gleiche   Verwendung fstream getline (Zeile für Zeile).   cp dauert fast 2 Minuten kopieren die   Datei.

In diesem Fall your're Hardware-gebunden. cp hat lesen und zu schreiben, und wird hin und her über die Plattenoberfläche wie verrückt bestrebt sein, wenn sie es tut. So wird es (wie Sie sehen) mehr als doppelt so schlimm wie die einfach ‚lesen‘ Fall.

Um die Geschwindigkeit zu verbessern, ist das erste, was ich versuchen würde, ist eine schnellere Festplatte oder ein SSD.

Sie haben nicht gesagt, was die Plattenschnittstelle ist? SATA ist so ziemlich die einfachste / schnellste Option. Auch (offensichtliche Punkt, dies ...) sicherstellen, dass die Platte physisch auf der gleichen Maschine ist Ihr Code ausgeführt wird, sonst bist du netzgebundenen ...

Andere Tipps

Ich würde auch vorschlagen Memory-Mapped-Dateien, aber wenn Sie Boost verwenden werden Ich denke, boost :: iostreams :: mapped_file ist ein besseres Spiel als boost :: inter.

Vielleicht sollten Sie Memory-Mapped-Dateien suchen.

Überprüfen Sie sie in dieser Bibliothek: Boost.Interprocess

Nur ein Gedanke, aber vermeiden, mit std :: endl, da dies einen Flush zwingen wird, bevor der Puffer voll ist. Verwenden Sie '\ n' stattdessen für eine neue Zeile.

Sie keine neuen verwenden, um die Puffer so zuzuordnen:

Versuchen: std :: vector <>

unsigned int      buffer_size = 64 * 1024 * 1024; // 64 MB for instance.
std::vector<char> data_buffer(buffer_size);
_file->read(&data_buffer[0], buffer_size);

Lesen Sie auch den Artikel über mit Strich in Bezeichnernamen: . Beachten Sie den Code ist in Ordnung, aber.

Mit getline () ineffizient sein kann, weil die String-Puffer benötigen die Größe neu bestimmt mehrmals werden, wie Daten aus dem Strompuffer angehängt werden. Sie können diese effizienter gestalten, indem pre-Sizing der Zeichenfolge:

Sie können auch die Größe der iostreams eingestellt Puffer entweder sehr groß oder NULL (für ungepufferte)

// Unbuffered Accesses:
fstream file;
file.rdbuf()->pubsetbuf(NULL,0);
file.open("PLOP");

// Larger Buffer
std::vector<char>  buffer(64 * 1024 * 1024);
fstream            file;
file.rdbuf()->pubsetbuf(&buffer[0],buffer.size());
file.open("PLOP");

std::string   line;
line.reserve(64 * 1024 * 1024);

while(getline(file,line))
{
    // Do Stuff.
}

Wenn Sie die Datei selbst puffern gehen, dann würde ich einige Tests mit ungepufferten I / O beraten (setvbuf auf eine Datei, die Sie fopened haben, können Sie die Bibliothek Pufferung deaktivieren).

Grundsätzlich, wenn Sie sich puffern gehen, möchten Sie die Bibliothek der Pufferung deaktivieren, da es nur geht Sie Schmerzen verursachen. Ich weiß nicht, ob es eine Möglichkeit ist, dass für STL ich zu tun / O, so dass ich empfehlen, geht bis auf die C-Level-I / O.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top