Lesebuffer-Größe für Dateien
-
Bin mir nicht sicher, in welches Unterforum das gehört.
Also: Bekanntlich gestaltet sich ja der Zugriff auf ein Speichermedium, etwa einer Festplatte, um ein Vielfaches langsamer als ein Zugriff auf den Hauptspeicher. Wenn ich als z.B. eine Funktion wie ReadFile() aufrufe, um Daten aus einer Datei in einen programmeigenen Buffer im Hauptspeicher zu befördern, und etwa das Programm in der Hauptsache damit beschäftigt ist, einzelne Felder in der Tabelle zu finden, kann der Lesebuffer doch gar nicht groß genug sein (d.h. natürlich ist es Unfug, etwa bei konstant 10-Byte großen Feldern einen 10-Byte großen Lesebuffer an ReadFile zu übergeben, dann den Inhalt des Buffers mit einem gesuchten Wert zu vergleichen, und bei missglückten Vergleich sofort wieder ReadFile(table_file,ten_bytes-small_buffer) aufzurufen, eben so lange, bis irgendwann einmal die 10 Bytes im Lesebuffer mit dem gesuchten Wert zusammenpassen. Bei tausenden Feldern hieße das dann ja tausendfachen Zugriff auf ein Speichermedium. Sicherlich wäre es da effizienter, sofort einen riesigen Lesebuffer zu verwenden, der z.B. 10000 Byte groß ist, dann ReadFile() nur ein einziges Mal aufzurufen (wobei wir aber diesmal verlangen, dass ReadFile() nicht nur 10 sondern 10.000 Byte in den Buffer lesen soll), und anschließend wenden wir uns den 1000 Feldern zu, die jetzt im Hauptspeicher stehen, und wir kommen garantiert viel schneller das gesuchte Feld. Man könnte also auch bei einer mehrere Megabyte großen Datei, die nach diesem 10-Byte-pro-Feld-Muster aufgebaut wäre, immer schön häppchenweise nach und nach mit so einem 10.000 Byte großen Buffer zum Ziel gelangen.
Falls ich bis hier her völligen Unsinn daherschwafle, BITTE weist mich auf die Irrtümer in der Theorie hin.So, und jetzt zur Frage: Wie groß sollte so ein Lesebuffer denn jetzt sein? Gibt es da eine sinnvolle Obergrenze, die man nicht überschreiten sollte? Man kann ja mit der Funktion GlobalMemoryStatus(LPMEMORYSTATUS m) herausfinden, wieviel Arbeitsspeicher von seiten des Betriebssystems überhaupt zur Verfügung stehen, also wäre die Versuchung groß, sofort mit
char* Lesebuffer=new char[m->dwAvailPhys];
sich den zur Verfügung stehende freien Arbeitsspeicher unter den Nagel zu reißen (das könnten dann 100 MByte oder mehr sein). In diesem Falle sollte ein 10-Byte großes Feld auch in einer mehrere Gigabyte großen Datei im Null komma nichts ausfindig zu machen sein, weil alle Vergleichsoperationen mit Daten stattfinden, die bereits im Hauptspeicher stehen (und nicht erst Feld-für-Feld in einen Minibuffer befördert werden müssten).
Im Regelfall sind aber solche Datenbanken ja nicht gleich mehrere Gigabyte groß, und dann wäre das sicher nicht angemessen, sofort den kompletten Speicher zu allokieren (nur um in einer 100kByte großen Datei irgend etwas schneller finden zu können).Meine Frage ist also im Wesentlichen: Wie denke ich mir eine vernünftige, einer Aufgabe angemessene Größe für einen Lesebuffer aus?
(Falls die Frage in ein anderes Unterforum gehört, bitte verschieben)
-
Also dein new char[available_memory] akzeptiert das OS sicher nicht. Wieso bildest du dir ein, dass Festplattenzugriffe so furchtbar langsam sind? Stimmt ja gar nicht. Außerdem hab ich den Verdacht, du lässt ReadFile synchron lesen, dabei ist doch asynchrones Lesen viel schneller, und bei so großen Datenmengen wie in deinem Fall auch notwendig. Eine passable Größe für einen synchronen Lesebuffer ist bei ca. 20 MB anzusiedeln, ein asynchroner Lesebuffer darf viel kleiner sein (Da reichen 10 kB locker aus)!
Der Experte hat gesprochen.
-
Für so etwas stellt dein Betriebssystem dir in der Regel eine Funktion bereit, um Dateien direkt in den Speicher zu mappen. Das geht schneller und ist bequemer.
Unter POSIX (Linux,Unix etc.) siehe man: mmap(2).
-
Windows: CreateFileMapping