Auf einzelne Zeichen in einer Datei zugreifen? (C ++)

8

Ich habe immer angenommen, dass es beim Verarbeiten von Textdateien effizienter ist, zuerst den Inhalt (oder einen Teil davon) in ein std :: string oder char-Array zu lesen, da - von meinem begrenzten Verständnis her - Dateien gelesen werden aus dem Speicher in Blöcken viel größer als die Größe eines einzelnen Zeichens. Wie auch immer, ich habe gehört, dass moderne Betriebssysteme oft nicht direkt aus der Datei lesen, so dass mein Input von der manuellen Pufferung wenig profitiert.

Angenommen, ich möchte die Nummer eines bestimmten Zeichens in einer Textdatei bestimmen. Wäre das Folgende ineffizient?

%Vor%

Zugegeben, ich denke, es hängt von der Dateigröße ab, aber hat irgendjemand irgendwelche allgemeinen Regeln darüber, was der beste Ansatz ist?

    
user1892721 10.12.2012, 20:30
quelle

3 Antworten

0

Nein, Ihr Code ist effizient. Dateien sollen sequentiell gelesen werden. Hinter den Kulissen ist ein RAM-Block reserviert, um den eingehenden Datenstrom zu puffern. Da Sie Daten verarbeiten, bevor die gesamte Datei gelesen wurde, sollte Ihre while-Schleife etwas früher fertig sein. Darüber hinaus können Sie eine Datei verarbeiten, die weit über den Haupt-RAM Ihres Computers hinausgeht.

Edit: Zu meiner Überraschung ist Jerrys Nummer klar. Ich hätte angenommen, dass jede Effizienz, die durch das Lesen und Parsen in Blöcken erzielt wird, durch die Kosten des Lesens aus einer Datei in den Schatten gestellt würde. Ich würde gerne wissen, wo diese Zeit verbracht wird und wie viel weniger die Variation ist, wenn die Datei nicht zwischengespeichert wird. Nichtsdestotrotz muss ich Jerry's Antwort zu diesem Thema empfehlen, besonders da er darauf hinweist, dass man sich wirklich keine Gedanken darüber machen sollte, bis man weiß, dass man ein Performance-Problem hat.

    
John McFarlane 10.12.2012, 20:50
quelle
10

Hier hängt sehr viel davon ab, wie kritisch die Performance wirklich für Sie / Ihre Anwendung ist. Das hängt wiederum davon ab, wie groß die Dateien sind, mit denen Sie es zu tun haben. Wenn Sie mit zig oder hundert Kilobyte arbeiten, sollten Sie im Allgemeinen einfach den einfachsten Code schreiben, der funktioniert und sich nicht viel Sorgen macht es - alles, was Sie tun können, wird im Wesentlichen sofort sein, so wird die Optimierung des Codes nicht wirklich viel erreichen.

Wenn Sie andererseits viele Daten verarbeiten - in der Größenordnung von mehreren zehn Megabyte oder mehr - können Unterschiede in der Effizienz ziemlich erheblich werden. Wenn Sie keine spezifischen Schritte unternehmen, um diese zu umgehen (z. B. read verwenden), werden alle Ihre Lesevorgänge gepuffert - aber das bedeutet nicht bedeutet, dass alle dieselbe Geschwindigkeit (oder auch unbedingt) haben sogar sehr nahe an der gleichen Geschwindigkeit).

Lasst uns zum Beispiel einen kurzen Test mit ein paar verschiedenen Methoden machen, um im Wesentlichen das zu tun, wonach du gefragt hast:

%Vor%

Ich habe das mit einer Datei von etwa 44 Megabyte als Eingabe ausgeführt. Bei der Kompilierung mit VC ++ 2012 habe ich folgende Ergebnisse erhalten:

%Vor%

Verwendung der gleichen Eingabe, aber kompiliert mit g ++ 4.7.1:

%Vor%

Obwohl alle Lesevorgänge gepuffert sind, sehen wir eine Variation von etwa 8: 1 mit g ++ und etwa 20: 1 mit VC ++. Natürlich habe ich nicht jede Möglichkeit getestet, die Eingabe zu lesen. Ich bezweifle, dass wir eine viel größere Bandbreite an Zeiten sehen würden, wenn wir mehr Lesetechniken testen würden, aber ich könnte mich damit irren. Ob wir es tun oder nicht, wir sehen genug Variation, dass zumindest wenn Sie eine Menge Daten verarbeiten, Sie durchaus berechtigt sein könnten, eine Technik gegenüber einer anderen zu wählen, um die Verarbeitungsgeschwindigkeit zu verbessern.

    
Jerry Coffin 10.12.2012 21:58
quelle
0

Es hängt weitgehend vom Kontext ab, und da der Kontext, der den Code umgibt, abwesend ist, ist es schwer zu sagen.

Machen Sie sich keinen Fehler, Ihr Betriebssystem speichert wahrscheinlich zumindest einen kleinen Teil der Datei für Sie, wie andere gesagt haben ... Das Hin- und Hergehen zwischen Benutzer und Kernel ist jedoch teuer, und das ist wahrscheinlich der Punkt, an dem Ihr Engpass liegt von kommen.

Wenn Sie vor diesem Code fin.rdbuf()->pubsetbuf(NULL, 65536); einfügen, bemerken Sie möglicherweise eine deutliche Beschleunigung. Dies ist ein Hinweis für die Standardbibliothek, 65536 Bytes gleichzeitig aus dem Kernel zu lesen und sie später für Ihre Verwendung zu speichern, anstatt zwischen Benutzer und Kernel für jedes Zeichen hin- und herzuwechseln.

    
Sebivor 22.05.2015 03:36
quelle

Tags und Links