Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi BlockRead/Write: Buffergröße = Schnelligkeit? (https://www.delphipraxis.net/110907-blockread-write-buffergroesse-%3D-schnelligkeit.html)

Helmi 26. Mär 2008 15:15


BlockRead/Write: Buffergröße = Schnelligkeit?
 
Hallo,

mittels folgenden Code (Ausschnitt) kopier ich eine Datei:

Delphi-Quellcode:
while FileLength > 0 do
  begin
    BlockRead(FromF, Buffer[0], SizeOf(Buffer), NumRead);
    FileLength := FileLength - NumRead;

    BlockWrite(ToF, Buffer[0], NumRead);

    PB_Position := PB_Position + NumRead;
  end;
den Buffer definier ich so (alle anderen Variablen sind für
meine Frage unwichtig):

Delphi-Quellcode:
  Buffer: array[0..100000] of char;
Nun meine Frage:
Ist meine Annahme richtig: Je größer der Array-Buffer,
desto schneller geht das kopieren?

Und falls ja, was ist das Maximum des Buffers?
(ich denke mal Arbeitsspeicher begrenzt die Größe)

bzw. Welche Größe sollte das Array sinnvollerweise haben?

Muetze1 26. Mär 2008 15:42

Re: BlockRead/Write: Buffergröße = Schnelligkeit?
 
Wozu legst du dir eine solche grosse Struktur auf dem Stack an? Hast du zuviel davon? Alloziiere dynamisch Speicher dafür!

Und die Buffergröße hängt damit zusammen, aber zu große Buffergrößen können den Kopiervorgang auch wieder verlangsamen. Du könntest dich über die Clustergröße beim jeweiligen Laufwerk kundig machen, wenn du das optimieren willst, aber ansonsten sollte ein Buffer von vllt. 32 KB - 128 KB reichen.

Aber was mich noch viel mehr stört: Warum verwendest du die alten Pascal Dateiroutinen? Warum nutzt du keine Streams? Die machen das entsprechend für dich (Delphi-Referenz durchsuchenTStream.CopyFrom()) und vor allem sind sie viel besser geeignet als die veralteten Routinen.

devidespe 26. Mär 2008 16:01

Re: BlockRead/Write: Buffergröße = Schnelligkeit?
 
TFileStream wäre der geeigntee Datentyp, mit dem man unter heutigen 32-Bit Umgebungen effizient Dateien kopiert. Die BlockWrite/BlockRead-Funktionen sind noch ein Relikt aus TurboPascal/BorlandPascal-Zeiten und quasi obsolete (sie werden also nur noch aus Kompatibilitätsgründen unterstützt).

So könnte ein entsprechender Quellcode inkl. Fehlermanagement aussehen:

Delphi-Quellcode:
VAR SourceFile : TFileStream;
    TargetFile : TFileStream;
BEGIN
  SourceFile:=TFileStream.Create('QUELLDATEI.TXT', fmOpenRead);
  TRY
    TRY
      TargetFile:=TFileStream.Create('ZIELDATEI.TXT', fmCreate OR fmShareDenyRead);
      TRY
        TargetFile.CopyFrom(SourceFile, SourceFile.Size);
      FINALLY
        FreeAndNil(TargetFile);
      END;
    FINALLY
      FreeAndNil(SourceFile);
    END;
  EXCEPT
    ShowMessage('Fehler aufgetreten.');
  END;
END;

Helmi 26. Mär 2008 16:04

Re: BlockRead/Write: Buffergröße = Schnelligkeit?
 
Hallo Mütze,

danke für den Tip.

TStream.CopyFrom hab ich gar nicht gekannt - schaut ganz gut aus.

Hier mal ein kurzer Auszug aus der Hilfe zu CopyFrom:
Zitat:

CopyFrom kopiert die in Count angegebene Anzahl Bytes aus dem in Source angegebenen Stream in den Stream. Dann verschiebt es die aktuelle Position um die in Count angegebene Anzahl Bytes und gibt die Anzahl der kopierten Bytes zurück.
Da ich in einer ProgressBar den Kopierverlauf anzeigen lassen möchte, so könnt ich ja, wenn ich das richtig verstehe, das Count zufällig angeben (z. B. 1000) und dann in einer Schleife solange 1000 Byte kopieren lassen, bis die Datei fertig ist.
Würd das so funktionieren?

Zacherl 26. Mär 2008 18:33

Re: BlockRead/Write: Buffergröße = Schnelligkeit?
 
Oder über die APIs CreateFile, GetFileSize, WriteFile / ReadFile, CloseHandle. Damit könntest du über GetFileSize die Größe der Zieldatei bestimmen und dann über GetMem dynamisch Speicher alloziieren. Wobei du natürlich auch hier Stückweise vorgehen kannst. (Über SetFilePointer kannst du die aktuelle Position ändern).

Oder wenns ganz simpel sein darf einfach CopyFile verwenden.

Muetze1 26. Mär 2008 21:38

Re: BlockRead/Write: Buffergröße = Schnelligkeit?
 
Zitat:

Zitat von Helmi
Da ich in einer ProgressBar den Kopierverlauf anzeigen lassen möchte, so könnt ich ja, wenn ich das richtig verstehe, das Count zufällig angeben (z. B. 1000) und dann in einer Schleife solange 1000 Byte kopieren lassen, bis die Datei fertig ist.
Würd das so funktionieren?

Ja, würde es, aber es würde den Kopiervorgang auch wieder verlangsamen, da du es künstlich aufhälst mit der Aktualisierung der GUI und explizit den Vorgang in Einzelschritte aufteilst. Diese Aufteilung kann (bzw. wird wahrscheinlich sogar) ineffizienter sein als ein CopyFrom() ohne explizite Teilung.

Helmi 26. Mär 2008 21:43

Re: BlockRead/Write: Buffergröße = Schnelligkeit?
 
wie würdest du es machen?

könntst mir da mal ein beispiel machen?

Muetze1 26. Mär 2008 22:07

Re: BlockRead/Write: Buffergröße = Schnelligkeit?
 
Wenn ich Nutzer bin, dann will ich ein schnelles und sicheres Programm was sich möglichst intuitiv bedienen lässt. Von daher:

- Wenn es sich um mehrere Dateien handelt, dann bau den Progressbar über die Dateianzahl auf.
- Wenn es sich um eine Datei handelt, dann setze einfach nur Screen.Cursor auf crHourGlass und im Finally auf crDefault zurück
- Wenn es eine grosse Datei ist, dann nutze den Shell Kopierfunktion mit dem Callback und stelle die Progressbar über den Callback dar.

himitsu 24. Apr 2008 19:16

Re: BlockRead/Write: Buffergröße = Schnelligkeit?
 
wie schon erwähnt, wäre es hier besser auf die "alten" Pascal-Routinen zu verzichten,
dnn diese haben meißt eine Pufferung (also einen eigenen Ziwischenspeicher, über den alles umgeleitet wird)

und bei den sonstigen Funtionen/Klassen kommt immernoch die WindowsFileCache ins Spiel.

Tipp: mal bei den FileSplittern im Forum hier umsehn ... die sind ja auf "schnelles" und "optimales" Kopieren ausgelegt.
(auch mal zum Thema NonCached umsehn)

Aber Muetze1's Vorschläge zeigen die "einfachen" Lösungswege.

Bei Dateioperationen sind aber Puffergrößen in vielfachen 512 Byte zu empfehlen
(z.B. 8 KB, 16 KB ... bis "maximal" 64 KB)


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:00 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz