Schnelles Lesen großer Textdateien in C



  • Hallo,

    weiß jemand einen anderen Befehl ausser fread für das effiziente, sehr schnelle Lesen sehr großer Textdateien?

    Danke & Gruß

    klemens



  • kjesse schrieb:

    weiß jemand einen anderen Befehl ausser fread für das effiziente, sehr schnelle Lesen sehr großer Textdateien?s

    C kennt nichts schnellers als fread().



  • Einfach große Blockgrößen auf einmal einlesen. Ob zu große Datenanforderungen Kontraproduktiv sind, weiß ich aber nicht. Damit vermeidest du aber schon allein den Overhead durch die vielen Funktionsaufrufe. Der Aufruf lässt sich auch dahingehend optimieren, indem man mit einem vielfachen der Blockgröße des Systems arbeitet. Das kann dann aber wieder von vielen Faktoren abhängen, zum Beispiel Quelle oder Betriebssystem.



  • Probiere mal setvbuf mit Blockgrößen >=4096



  • springe zum Ende der Datei, lass dir die Position in der Datei mit ftell angeben, erzeuge mit malloc einen entsprechend großen Bereich im heap, springe zum Anfang und lies alles mit einem Mal per fread ein.

    Ist glaub ich der schnellste Weg. Ansonsten eben mit den Blockgrößen spielen. Spielen



  • Hallo,

    vielen Dank für die tollen Tipps. 👍 Mit der Blockgröße habe ich bereits rumgespielt. 4K schien mir am schnellsten, da es wohl die Systemgröße meines Betriebssystems (Ubuntu) ist. Aber ich habe nicht ganz verstanden, wie man mit setvbuf aus einem Stream lesen kann. Ist das noch schneller?

    Gruß

    Klemens



  • Wenn du Linux benutzt kannst du dir auch mal mmap anschauen



  • Mit setvbuf selbst kannst du nicht lesen, das setzt einen (für dich unsichtbaren) Puffer für Lese/Scheibaktionen für den angegebenen FILE-Zeiger.
    RTFM



  • Ich kann eigentlich nur sagen wie ich das immer mache:

    fd = open( ...); // binäres Open zum Lesen
    size = filelength( fd); // Länge bestimmen
    ptr = malloc( size); // Speicher holen
    read( fd, ptr, size); // in einem Rutsch lesen, den blockweisen Kram macht das OS
    

    (Fehlerhandling habe ich mal weggeslassen. Mit den unbuffered Funktionen sollte
    das schneller sein wie buffered IO.)



  • Eventuell (jaja ich weiß es ist das C-Forum ;)) könnten auch Systemspezifische Funktionen schneller sein. Falls portabilität also kein wichtiger Faktor ist könntest du das ja mal testen.



  • Es wurde an sich alles gesagt.
    Ob man 4k oder mehr haben mag, sollte man ausmessen.
    Normalerweise gehen die Messungen so aus:
    Bis 2k sieht man deutlich, daß größere Blöcke besser sind. 2k oder 4k sind schon knapp, aber man sieht es noch, wenn man genau hinguckt. Über 4k sind sogar noch schneller, aber im Bereich weniger Promille, da habe ich ein schlechtes Gewissen den anderen Anwendugen gegenüber, denen ich Speicher wegnehme.
    Bei 64-Bittern nehme ich 8k. Sonst 4k.
    Alles auf einmal mag ich nicht einlesen, weil ich dazu vorher beim Einlesen warten muß, bis alles da ist, und erst später mit der Verarbeitung anfangen darf. Normale f-Funktionen erlauben es mir, das zu verschränken, zu geringen Kosten, dem immerwährenden if(amEndeSchon) readNexBuffer();. Die sind aber sehr klein.
    Mit OS-spezifischen Funktionen mmap oder CreateFileMapping kriegt man dieses if sogar noch weg. Aber auch das ist kaum messbar.


Log in to reply