![]() |
AW: Viele Dateien performant einlesen
Liste der Anhänge anzeigen (Anzahl: 1)
..."Ich habe eine Vielzahl (ein paar Tausend) CSV-Dateien. Die möchte ich allesamt auswerten."...
Nun ja, ich hätte da ein paar Millionen(~3Mio) Dateien(a ~8KB) in ein paar tausend Verzeichnissen(~180000) und renne da ständig durch... wo ist das Problem: - über alle Dateien * FileStream öffnen und StreamSize ermitteln * bei den "Spielzeuggrößen" mit einem Schlag vom FileStream in RAM Buffer einlesen * FileStream freigeben(schließen) * keine Verarbeitung oder sonst was! * nächste Datei - Zeit messen Man könnte auch hier zwar per WinApi Funktionen und direktem RAM Puffer ein paar MicroSekunden sparen, aber FileStream reicht hier vollkommen aus. (Nebenbei: Bei "großen Dateien" einfach mal fach TFastfileStream googeln... da findet sich dann was schönes mit MemoryMappedFiles:)) Wenn das OK, dann mit etwas Hirnschmalz ein eigenes "GetLine" geschrieben(einfach per BYTE Pointer durch den Rambuffer nach "CR" suchen und wenn CR gefunden es durch "NULL" ersetzen und die nun "NullTerminierte" Line ab vorherigem Pointer(bzw. anfangs "@0") weiter auswerten. Gleiches Spiel nun innerhalb der Line. CSV-Trennzeichen fortlaufend suchen und gefundene Positionen+1 in BytePtrArray speichern und Inhalt des Pointers auf "0" setzen... Bingo: nun haben wir ohne jegliches Umkopieren irgendwelcher Speicher/Strings ein PtrArray mit lauter Pointern vom Typ PChar(bzw. PAnsiChar), welche wir problemlos verarbeiten, vergleichen, kopieren oder was auch immer können... (Sorry für meine Vorliebe für NullTerminierte Strings auf Pointer-Basis, ich denke immer noch in "C" und nutze Delphi/Pascal nur weil es sein muss;)) TStringList ist zwar schön, aber im Masseneinsatz ist deren LoadFromXXX als "ReadLN" doof. Wenn es schnell gehen soll, dann 3 Threads... 2x FileStreamLoad, 1x "RAM-CSV-Explode"... Results dann in weiterem Thread speichern/verarbeiten... damit sollte QuadCore gut ausgelastet werden. |
AW: Viele Dateien performant einlesen
Zitat:
Die von dir gemessenen Ergebnisse kann ich aber überhaupt nicht nachvollziehen:
Code:
CreateDataClick
CreateFiles 0:00:14.527 ReadClick GetFiles 0:00:00.007 ReadFiles 0:00:01.692 Split 0:00:03.112 CreateDataClick CreateFiles 0:00:09.681 OpenClick GetFiles 0:00:00.006 Open 0:00:02.614 ReadClick GetFiles 0:00:00.006 ReadFiles 0:00:01.649 Split 0:00:03.336 |
AW: Viele Dateien performant einlesen
Zitat:
Nach Deiner Methode mußt Du jede erstellte Zeile überprüfen ob sie vollständig ist, da doch lieber gleich richtig. Gruß K-H |
AW: Viele Dateien performant einlesen
Doch, also bei mir ist es ähnlich:
Code:
openClick
GetFiles 50269 ticks, 16 ms Open 745099 ticks, 238 ms readClick GetFiles 90555 ticks, 29 ms ReadFiles 3411398 ticks, 1094 ms Split 15388554 ticks, 4935 ms stringListRead 3179206 ticks, 1019 ms
Delphi-Quellcode:
ist jetzt einfach nur ein TStringList-LoadFromFile, also im Endeffekt praktisch das gleiche wie ReadFiles nur mit einem leicht anderen
stringListRead
Delphi-Quellcode:
zum Öffnen der Dateien.
FileMode
Jetzt das Wichtige: Wir übersehen bei diesen Benchmarks hier alle den Windows-Cache hinter den Kulissen! Ich war grade auch verdutzt über meine Zeiten: Wie kam ich denn auf 45 Sekunden? Dann habe ich ![]() Um aussagekräftige Messungen zu machen sollte man wohl vor jedem Durchgang einmal komplett den Windows File Cache leeren. Das werde ich im Verlauf des Tages auch nochmal machen... Auf jeden Fall vielen Dank für die rege Teilnahme an alle! :thumb: |
AW: Viele Dateien performant einlesen
Zitat:
![]() |
AW: Viele Dateien performant einlesen
Die Antwort ist 134217728 ;)
Delphi-Quellcode:
Damit liest er die 5000 Dateien in 160-400 ms komplett ein, auch wenn diese gerade frisch erzeugt wurden.
procedure TForm1.btnOpenLowLevelClick(Sender: TObject);
var AFiles : TStringDynArray; fh : THandle; fl, fr : LongWord; i : integer; Buffer : Pointer; begin Watch.Start; AFiles := TDirectory.GetFiles(FDir); Watch.Stop; Prot('GetFiles', Watch); Watch.Reset; for i := Low(AFiles) to High(AFiles) do begin Watch.Start; fh := CreateFile(PChar(AFiles[i]), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0); // Optimiert für nur vorwärts lesen fl := GetFileSize(fh, nil); fr := 0; GetMem(Buffer, fl); ZeroMemory(Buffer, fl); ReadFile(fh, Buffer^, fl, fr, nil); CloseHandle(fh); FreeMem(Buffer); Watch.Stop; end; Prot('Lowlevel open', Watch); Watch.Reset; end; |
AW: Viele Dateien performant einlesen
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:56 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz