Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi ReadFileScatter/WriteFileGatter (https://www.delphipraxis.net/82843-readfilescatter-writefilegatter.html)

himitsu 20. Dez 2006 13:47


ReadFileScatter/WriteFileGatter
 
Liste der Anhänge anzeigen (Anzahl: 2)
Moin,

ist zufällig in Sachen ReadFileScatter jemand weitergekommen?


Denn nach meinem Testprogramm bringt dieses anscheinend "nur" Nachteile.


Es ist ja schließlich nicht schneller als ein "normales" asynchrones und noncached ReadFile,
nur daß man erst den Speicher "mühevoll" in kleine Häppchen (je 1x SystemPageSize) zerlegen muß. :wall:

Und wenn genügend Teile bereits in der WindowsFileCache liegen, dann sind die "langsamen", darüber laufenden Funktionen schneller.
z.B. die über 700 MB/s, bei zwei 128 MB-Dateien sind ja wohl nicht zu verachten... :roll:


Im Anhang natürlich mein Testprojektchen, :angel:
zusammen mit den anderen Lese-Methoden.


PS:
laut meinem PSDK (WinXP SP2) soll FILE_SEGMENT_ELEMENT angeblich so aussehen:
Code:
typedef union _FILE_SEGMENT_ELEMENT {
    PVOID64 Buffer;
    ULONGLONG Alignment;
} FILE_SEGMENT_ELEMENT;
Delphi-Quellcode:
Type FILE_SEGMENT_ELEMENT = packed Record
    Buffer: Pointer64;
    Alignment: UInt64;
  End;
wie man sieht is alles 64 Bit groß, weßhalb ich es so definiert hatte:
Delphi-Quellcode:
Type FILE_SEGMENT_ELEMENT = packed Record
    Buffer, _fill: Pointer;
    Alignment: UInt64;
  End;
allerdings funktioniert es nur, wenn 32 Bit verwendet wird: :gruebel:
(wenn mehr als eine SystemPageSize gelesen werden soll)
Delphi-Quellcode:
Type FILE_SEGMENT_ELEMENT = packed Record
    Buffer: Pointer;
    Alignment: LongWord;
  End;

PSS:
Wenn zufällig noch jemand weiß wofür Alignment da sein soll?
Es hatte bei mir jedenfalls keine Auswirkungen und wenn MS was im Record freilassen wollte, dann heißt es ja sonst reserved, oder so.
Im PSDK steht zumindestens nichts drin.



[Anhang]
ClearCache: da ich ja keinen "direkten" einfluß auf die WindowsateiVerwaltung hab, kann/wird dieses vermutlich nicht bei jedem funktionieren ... als Ausweg könnte man auch den Rechner in den Ruhezustand (Hibernate) versetzen, denn da wird ebenfalls de FileCache geleert.

Im Bild sieht man verschiedene Testläufe, unter verschiedenen Bedingungen...
> mit FileCache
> mit FileCache - Dateien bereits geladen
> ohne FileCache

> auf dem selben Datenträger
> auf physich getrennten Datenträgern

Dann wurden noch die im Durchschitt besten Lese-Methoden angepunktet (markiert).


PS: wenn versucht wird gleichzeitig auf dem selben Laufwerk Dateien zu lesen/schreiben, dann wird natülich durch das ständige hin- und herspringen (zwischen den Dateien) alles ausgebremst.


[add]
Ich vergaß noch zu sagen, daß in den Sourcen keine Resourcenschutzblöcke und Fehlerabfragen vorhanden sind.
Für die kleine Demo werden diese nicht benötigt und würden wohl eher die Übersichtlichkeit über das Wichtigste behindern.
Wer also was daraus verwenden will, sollte sich dann die entsprechenden Dinge noch unbedingt einbauen!

himitsu 3. Jan 2007 18:20

Re: ReadFileScatter/WriteFileGatter
 
Liste der Anhänge anzeigen (Anzahl: 2)
Morschn,

beim weiteren Rumspielen mit ReadFileScatter/WriteFileGather ist unter Anderem auch noch dieses Programm rausgekommen.
Hier gibt es auch mal was zum Schreiben (WriteFileGather) ^^


Es ist sozusagen ein FileSplitter ... nocheiner :roll:

allerdings mal als sowas wie 'ne Konsolen-Anwendung mit MiniGUI.


'n Einblick in die möglichen Parameter:
Code:
FileSplitter -?                  // Hilfe
FileSplitter -s "abc.def" mb100  // Datei in 100MB-Stückchen zerlegen
FileSplitter -c "abc.def.part1" // Dateien wieder zusammensetzen
FileSplitter                    // GUI
Ohne Parameter und bei Falscheingaben kommen 2 bis 3 kleine Dialoge zur Parametereingabe.

In den Dialogen und per -? bekommt man natürlich Infos zu den einzelnen Parametern.


Und ja ich weiß ... für die Programmgröße wäre eine Abschaffung der Units SysUtils und Dialogs nicht schlecht.
Mal sehn, ob ich micn mal dazu durchringen kann diese abzuschaffen ... falls es jemand für nötig hällt. ._.

Eine Prozesanzeige fehlt und auf Resourcenschutzblöcke, sowie eine ordnungsgemäße Freigabe bei "Fehlern" wurde bewußt verzichtet,
da sich WinNT+ (NT4 2K XP Vista) ja auch schon so hervorragend um alle nötigen Dinge kümmert. :angel:



So, aber nun nochmal zu ein paar Besonderheiten und anderer Infos:
  • Zieldateiname wird aus der Quelldatei erzeugt
  • Zielverzeichnis entspricht dem Quellverzeichnis
  • SplitSize wird auf ein vielfaches der Sektor-Größe aufgerundet (meißt 512 Byte-Schritte)
    der Code würde sonst, auf Grund des NonCached-Read/Write, wesendlich aufwendiger werden müssen :?
  • Datum (LastWrite) und Attribute werden jeweils von der/den Ausgangsdatei(en) übernommen
    diese Daten gehen also nicht verloren
  • keine Fortschritsanzeige
    Ob das Programm noch läuft sieht man (nur) an den sich veränderten Dateien und im TaskManager,
    aber das Programmende wird entweder durch die Statistik, oder eine Exception angezeigt.
  • Registryeinträge, INIs, oder Ähnliches gibt es nicht
  • es wird mindestens Windows NT 4.0 SP2 benötigt
    siehe Requirements unter MSDN-Library durchsuchenReadFileScatter
zum QuellCode:
  • Kommentare gibt's kaum
  • 's ist vermutlich dennoch übersichtlich,
    vorallem da auf alles Überflüßig und Unnötige verzichtet wurde
    ansonsten ist der relevante Code recht kurz - abgesehn von den Prüfungen der Eingabeparameter...
  • ReadFileScatter und WriteFileGather zählen angeblich mit zu den schnellsten Dateiopperationen,
    wenn das stimmt, dann sollte dies der wohl schnellste FileSplitter sein :shock:
  • als Schreib-/Lesepuffer wurden mehrere aufeinanderfolgende Speicherblöcke verwendet, welche als Ganzes reserviert und dann Stückchenweise zugeordnet wurden
  • Resourcenschutzblöcke und Dergleichen fehlen,
    sind aber für diese Art von Programm nicht nötig (Windows kümmert sich darum)
    dennoch solltet ihr in euren Programmen soetwas vorsehen, jedenfalls wenn ihr nicht wißt wie sich Windows verhält :warn:


Falls noch Fragen offen sind oder Fehler auftreten, dann meldet euch einfach. :angel:
Ansonsten scheint das Programm bis jetzt fehlerfrei zu funktionieren.



PS: das Programm ist, auch wenn ich vermutlich irgendwann daran noch etwas weiterentwickle,
nicht wirklich für einen "Großeinsatz" gedacht ... vielmehr soll/kann es als Demo für die Verwendung von MSDN-Library durchsuchenReadFileScatter und MSDN-Library durchsuchenWriteFileGather diehnen.
Darum wird es vermutlich auch niemals mit so'ner schönen GUI wie bei den anderen FileSplittern ausgestattet

Luckie 3. Jan 2007 18:42

Re: ReadFileScatter/WriteFileGatter
 
Mach mal bitte Geschwindigkeitstet mit meinem FileSplitter.

Olli 7. Jan 2007 06:42

Re: ReadFileScatter/WriteFileGatter
 
Ich glaube hier liegt ein Mißverständnis über den Sinn der Funktionen vor. Sie können bspw. ja zum Datentransfer von und zu Geräten (logisch "Dateien") benutzt werden. Und da hängt es ganz vom Treiber ab, ob und wie er das implementiert und ob es dadurch schneller wird.

Auch kann es sein, daß jemand schon sowas wie einen Ringpuffer oder ähnliches hat. Dann würde ihm die Funktion u.U. entgegenkommen. Man benutzt eben immer die Werkzeuge, die einem am besten "zur Hand gehen".

Zitat:

Zitat von himitsu
Code:
typedef union _FILE_SEGMENT_ELEMENT {
    PVOID64 Buffer;
    ULONGLONG Alignment;
} FILE_SEGMENT_ELEMENT;
Delphi-Quellcode:
Type FILE_SEGMENT_ELEMENT = packed Record
    Buffer: Pointer64;
    Alignment: UInt64;
  End;
wie man sieht is alles 64 Bit groß, weßhalb ich es so definiert hatte:
Delphi-Quellcode:
Type FILE_SEGMENT_ELEMENT = packed Record
    Buffer, _fill: Pointer;
    Alignment: UInt64;
  End;

Du bist lustig ... das heißt, du übergibst mal eben eine 128bit-Struktur, wo nur eine 64bit-große stehen sollte?

Zitat:

Zitat von himitsu
Wenn zufällig noch jemand weiß wofür Alignment da sein soll?
Es hatte bei mir jedenfalls keine Auswirkungen und wenn MS was im Record freilassen wollte, dann heißt es ja sonst reserved, oder so.
Im PSDK steht zumindestens nichts drin.

Da es sich um eine UNION handelt, wird dieser Wert natürlich dem "Pointer" entsprechen, weshalb man durch ein einfaches logisches AND das Alignment bestimmen kann ...

Und jetzt husch husch nochmal schnell das Thema Unions in meinem DLL-Tut nacharbeiten ;) ...:

Delphi-Quellcode:
type
FILE_SEGMENT_ELEMENT = packed record
  case Integer of
    0: (Buffer: PVOID64);
    1: (Alignment: ULONGLONG);
end;
... bei der letzten Klammer bin ich nicht sicher, ob die vor oder nach dem Semikolon stehen muß, da ich zu faul bin BDS jetzt zu starten :stupid: ... achja, und die Typen mußt du natürlich auf Delphi zurechtschneidern. Habe ich hier der Einfachheit halber nicht gemacht. Bsp. #2:

Delphi-Quellcode:
type
FILE_SEGMENT_ELEMENT = packed record
  case Integer of
    0: (Buffer, _fill: Pointer);
    1: (Alignment: UInt64);
end;

himitsu 10. Jan 2007 17:49

Re: ReadFileScatter/WriteFileGatter
 
Liste der Anhänge anzeigen (Anzahl: 3)
Dat mit der union hatte ich bei der Übersetzung wohl dodal übersehn. :shock:
Also, Wenn man es so sieht, dann passen die Typengrößen natürlich ... hätte ja beinah schon die Vermutung bekommen, dat die es im 32-Bit-Windows anders definiert hatten. :roll:


Hab's entsprechend geändert :angel:


Hatte grad keine neue Version von deinem FileSplitter da ... aber daß das noch nicht optimierte langsamer ist, war ja wohl klar.

Code:
Testdatei: 2,4 GB
Meines:     9:39, 9:37
dein Altes: 16:18, 14:02  (5.5.5.1228 28.12.05)
ein aktuellerer Vergleich folgt vermutlich morgen.


Aber 'nen kleinen Test hatte ich dennoch mal gemacht ... ReadFileScatter ist wohl 'nen Hauch schneller gewesen
Code:
4.000.000.000 Byte

ReadFile+NoCache        89,828 s = 42,5 MB/s
ReadFile+NoCache+Async  67,797 s = 56,3 MB/s
ReadFileScatter         67,781 s = 56,3 MB/s
Ach ja, bei dem Testprogramm:
ersma "kleinen" Fehler behoben :shock:



dieses
Delphi-Quellcode:
FillMemory(@A1[0], SizeOf(A1), 0);
FillMemory(@A2[0], SizeOf(A2), 0);
durch Folgendes ersetzt
Delphi-Quellcode:
FillMemory(@A1[0], Length(A1) * SizeOf(FILE_SEGMENT_ELEMENT), 0);
FillMemory(@A2[0], Length(A2) * SizeOf(FILE_SEGMENT_ELEMENT), 0);
ReOpenFile-Ersatz eingefügt - wegen SetFilePointer + not sector-aligned + FILE_FLAG_NO_BUFFERING
siehe MSDN-Library durchsuchenSetFilePointer


Und dann noch einiges anderes nachgerüstet ... jetzt sollten wohl schonmal “alle“ möglichen Lese-/Schreibmethoden vorhanden sein.
Muß aber noch ein bissl was ändern ... ist halt nicht so ganz leicht ein halbwegs “gerechtes“ Prüfszenario für alle Metoden zusammenzustellen, vorallem wenn die etwas “chaotische und nicht zu steuernde“ SystemCache so mitspielen soll, wie sie es soll :wall:

[add]
ach ja, dat SetFilePointer+NotSectorAligned+FILE_FLAG_NO_BUFFE RING-Problem betraf natürlich auch dieses Programm, daher hier auch nochmal 'ne aktuelle Version ... 's wäre ja nicht schön wenn plötzlich ein paar Bytes mehr in der geteilten Datei auftauchen :roll:


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:21 Uhr.

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