Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Datei > 500mb vollständig in RAM laden (https://www.delphipraxis.net/95160-datei-500mb-vollstaendig-ram-laden.html)

Harry M. 2. Jul 2007 10:59


Datei > 500mb vollständig in RAM laden
 
Moinsen DP

Wie bekomme ich meine Datei möglichst schnell in den RAM um sie dort wie ein TFielStream oder TMemoryStream zubehandeln. Den fs öffnen un in einen ms kopieren, scheint mir nicht der richtige Weg. (Hat zu lange gedauert - ein víelfaches länger als sie einfach nur zukopieren, und nachdem immer noch nicht fertig geladen wurde aber schon viel mehr Speicher drauf ging, habe ich die Sache abgebrochen.)

Aber vielleicht lags auch nur am Code :gruebel:
Delphi-Quellcode:
function LoadTable(AFileName: String; var AResult: TMemoryStream): Boolean; overload;
var
  fs: TFileStream;
begin
  Result := False;
  if FileExists(AFileName) then begin
    fs := TFileStream.Create(AFileName, fmOpenRead);
    AResult := TMemoryStream.Create;
    AResult.CopyFrom(fs, fs.size);
    fs.Free;
    Result := AResult.Size > 0;
    end;
end;
Weiß doch sicher wieder jemand bescheid?! :mrgreen:

Die Muhkuh 2. Jul 2007 11:01

Re: Datei > 500mb vollständig in RAM laden
 
Hi Harry,

mach doch direkt ein MS.LoadFromFile ;-)

[edit]Wobei ich keinen Sinn dabei sehe, eine komplette 500mb Datei in den Ram zu laden. Was hast Du den vor? Vielleicht geht das auch anders. [/edit]

Daniel 2. Jul 2007 11:08

Re: Datei > 500mb vollständig in RAM laden
 
Wie wäre es denn mit sog. "MemoryMapped Files" und die restliche Arbeit dem OS überlassen?

Harry M. 2. Jul 2007 11:10

Re: Datei > 500mb vollständig in RAM laden
 
Äffffffffffffff. Genau das hab ich gestern gesucht und nich gefunden. :wall: :wall: :wall:
Danke.

Harry M. 2. Jul 2007 11:18

Re: Datei > 500mb vollständig in RAM laden
 
Hi Daniel,
MemoryMapped Files - gutes Stichwort. Da guck ich doch ma nach :mrgreen:

Edit: Ich versuch grad so ne Art Datenbank zubauen. Ohne dabei wirklich auch ADO und Co zusetzten. Denn bei Test ist mir aufgefallen, mit zunehmender Grösse sank auch die Performance der SQL anfragen rapiede Schon nach 15 Min inserst bei anlegen, kamem Zeiten > 200ms raus, was nicht akzeptabel ist.

Ich schreibe jetzte meine Daten zuerst in den Speicher und sicher dort aller paar Minuten in eine Datei. Das geht besser.

Der_Unwissende 2. Jul 2007 11:18

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Zitat von Daniel
Wie wäre es denn mit sog. "MemoryMapped Files" und die restliche Arbeit dem OS überlassen?

Etwas ganz ähnliches sollte doch eigentlich schon beim FileStream passieren. Der arbeitet (afaik) mit einem Lesepuffer (zumindesten ist der Zugriff hier schon gut schnell!). An sich ist halt die Frage, warum Du so darauf bestehst, dass die komplette Datei im RAM landet. Das sicher zu stellen ist imho etwas aufwändiger. Selbst bei MemoryMapped Files hat halt das OS die Möglichkeit (korrigiert mich, wenn ich mich irre!) den Inhalt in den Virtuellen Speicher zu verschieben, der liegt natürlich wieder auf der Festplatte. Das man davon so schön wenig merkt ist gerade die Aufgabe des OS, aber letztlich dürfte es Dir keine Perfomance-Vorteile bringen, wenn Du hier eine Datei schon komplett in den RAM lädst (da geht eher Zeit verloren, wenn diese Menge an Daten ausgelagert wird weil Platz im RAM gemacht werden muss oder dies eben mit anderen Programmen geschieht, da deine 500 MByte einfach unnötig Speicher blockieren).

Gruß Der Unwissende

Harry M. 2. Jul 2007 11:33

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Zitat von Der_Unwissende

An sich ist halt die Frage, warum Du so darauf bestehst, dass die komplette Datei im RAM landet.
Gruß Der Unwissende

Bei Ich schreibe in die Datei pro Eintrag 8 byte und einen Long. Jeztz weisst Du vielviele Einträge in der Datei stehten, wenn ich ca von 500mb ausgehe. Potenzierung nicht ausgeschlossen. Das suchen in der Datei geht später schneller als wenn ich die 8 Byte zu vergleichen von Platte lese.

Luckie 2. Jul 2007 11:39

Re: Datei > 500mb vollständig in RAM laden
 
Und bei einem 512 MB System bleiben dann noch 12 MB für Betriebssystem und dein Programm (das keine anderen Programme noch nebenbei laufen, habe ich gleich mal außen vor gelassen, da sehr unwahrscheinlich ist, dass man die noch gestartet bekommt bzw. vernünftig mit arbeiten kann). Selbst auf einem 1 GB System macht es nicht wirklich Freund zu arbeiten, wenn plötzlich die Hälfte vom Speicher fehlt.

Das die Performance in den Keller geht, wenn ich jedes Byte einzeln lade, dürfte irgendwie logisch sein. Arbeite mit einem entsprechenden Lesepuffer (512 KB) und du solltest auch keine Performance-Probleme haben.

Der_Unwissende 2. Jul 2007 11:42

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Zitat von Harry M.
Bei Ich schreibe in die Datei pro Eintrag 8 byte und einen Long. Jeztz weisst Du vielviele Einträge in der Datei stehten, wenn ich ca von 500mb ausgehe. Potenzierung nicht ausgeschlossen. Das suchen in der Datei geht später schneller als wenn ich die 8 Byte zu vergleichen von Platte lese.

Das ist klar, aber wenn Du einen Puffer verwendest, 8 Byte + sizeOf(Long) (denke ein Long ist in dem Bereich), z.B. 1.000.000 solcher Datensätze (knapp unter einem MByte), dann sollte das schon um einiges flinker gehen und sehr ressourcen-schonend arbeiten. Die größe des Puffers kannst Du natürlich auch sinnvoller wählen! Versuch einfach mal Werte zwischen ein paar Kilobyte und ein paar zig MByte und schau Dir an wie schnell was funktioniert.

[edit]
roter Kastern?!

Aber gleich eine Ergänzung, wie Luckie schon sagte, wirst Du schnell das Problem bekommen, dass Dir das OS schon gar nicht den gesamten RAM zur Verfügung stellen wird, es muss ja selbst auch noch laufen! Wenn sich dann 512 MByte noch potenzieren landest Du schnell bei den Grenzen eines 32-Bit Systems.
[/edit]

Elvis 2. Jul 2007 11:52

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Zitat von Harry M.
Hi Daniel,
MemoryMapped Files - gutes Stichwort. Da guck ich doch ma nach :mrgreen:

Edit: Ich versuch grad so ne Art Datenbank zubauen. Ohne dabei wirklich auch ADO und Co zusetzten.

Kein DBMS setzt auf ADO, außer dieser klägliche Versuch aus dem Hause MSFT. ADO ist eher ein Ärgernis, dass viele DBMS-Hersteller eingehen um damit Leute zu bedienen, die irgendwie ADO bevorzugen.
Diese doch sehr fundamentale Wissenslücke sollte dich eigentlich auf den Gedanken bringen, dass du dich a) nicht mit genügend unterschiedlichen DBMS auseinandergesetzt hast und das Ganze b) nicht lange genug (Erfahrung).

Jeder (JEDER) Versuch ein eigenes, auf eine spezielle App angepasstes, DBMS zu basteln, der mir bisher unter die Augen kam, war bestenfalls jämmerlich.
Zitat:

Denn bei Test ist mir aufgefallen, mit zunehmender Grösse sank auch die Performance der SQL anfragen rapiede Schon nach 15 Min inserst bei anlegen, kamem Zeiten > 200ms raus, was nicht akzeptabel ist.
Wenn deine Erfahrungen bei ADO aufhören, und wenn du schon bei solch' "simplen" Prblemenen scheiterst, wirst du keine Lösung hinbekommen, die mit einem embedded Firebird oder SQLite hinter einem eigenen Service auch nur ansatzweise konkurieren könnte.

Zitat:

Ich schreibe jetzte meine Daten zuerst in den Speicher und sicher dort aller paar Minuten in eine Datei. Das geht besser.
Und wie sicherst du ihn die Datei? Wonach entscheidest du was wann geschrieben werden muss? Was ist mit Stromausfällen oder gleichzeitigen Zugriffen?
Alles Dinge, die dir Firebird oder SQLite abnehmen würden, und beide machen diesen Job sehr gut. ;)

Harry M. 2. Jul 2007 12:15

Re: Datei > 500mb vollständig in RAM laden
 
Jo stimmt. Ich hab mich nicht lange genug mit den verschienden DBMS System auseinander gesetzt.
Wieviele davon gibt es? Und wieviel zeit bräucht ich um mich mit gründlich einzuarbeiten? Um dann auch noch das Beste für mich herraus zussuchen. Ich werde Deine Hinweise berücksichtigen und schaue ob ich mit Firebird besseres Ergebnisse erziele.

Die potenzierung erfogt natürlich geteilt. zB auf 1 GB pro Datei.

[AM_RANDE]
Bei 1 TB local zu Verfügung könnte ich auch einiges aufnehmen. Desweiten habe 2 Gb drinne, noch eine Bank frei, und noch aufrüstbar dank 64MB Grafik (muss aber erst warten wegen dem neuen DualChanel fähigen Bord) Falls das jemand wissen mag. :mrgreen:
[/AM_RANDE]

Sicherlich wird es nur ein kläglicher Versuch bleiben wenn ich es gegen ein "ordentliches" DBMS vergleiche. Ist auch ehr nur der als Station auf dem Weg zu der Erfahrung gedacht, von der Du sprichst.

mkinzler 2. Jul 2007 12:33

Re: Datei > 500mb vollständig in RAM laden
 
Selbst wenn man auf ein DBMS verzichten will, würde ich nie auf die Idee kommen, die komplette "Datenbank" im Speicher zu halten. in diesem Fall würde ich nur den Index (als Binärbaum o.ä.) im Speicher halten, welcher dann auf die Recordnummern in der Datei verweist. Diese würden sequentiell geschrieben und ein Ordnung nur per Index erreicht, welcher zusätzlich zum Speicher spätestens beim beenden des Programmes auf Platte gesichert werden sollte.
Aber ich sehe es wie Elvis: Ein solche Lösung würde viel mehr Arbeit als die Einarbeitung in ein DBMS bedeuten und wohl nicht ansatzweise an die Performance herankommen.

Harry M. 2. Jul 2007 12:41

Re: Datei > 500mb vollständig in RAM laden
 
Ist meine Idee im Hinterkopf. :zwinker:
nur ist mir noch nicht ganz klar wie ich so einen Index machen könnte. Muss ja am Ende auf eine mathematische Formel beruhen.... und wenn die dann halbwegs funzen sollte. werde ich die Dateien sicher nicht mehr im Ram halten. Wo sie ohne hin nur geladen werden wenn Sie gebraucht würden.

mkinzler 2. Jul 2007 12:48

Re: Datei > 500mb vollständig in RAM laden
 
Als Index würde sich ein Binärbaum eigenen (dieses Problem hat wohl fast jeder hier in der Schule/Uni usw schon mal Lösen dürfen)

Harry M. 2. Jul 2007 12:52

Re: Datei > 500mb vollständig in RAM laden
 
Dann sollte sich da ja was finden lassen (läuft ja auch grad noch ein Thread zu dem Thema)

Der_Unwissende 2. Jul 2007 12:57

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Zitat von mkinzler
Als Index würde sich ein Binärbaum eigenen (dieses Problem hat wohl fast jeder hier in der Schule/Uni usw schon mal Lösen dürfen)

Nimm lieber gleich einen B+/B*-Baum, die können nicht entarten! Das ganze ist aber nur der erste Schritt in Richtung DBS. Da werden Datensätze auch nur in Seiten gespeichert/verwaltet. Man speichert immer nur die Referenz auf eine bestimmte Seite und auf der Seite auf den Eintrag. Reicht nach einer Veränderung der Platz nicht mehr aus, wird hier noch eine zusätzliche Indirektion (auf den tatsächlichen aktuellen Speicherort) gespeichert (weniger aufwendig als die Indexierung/alle Verweise zu aktualisieren).
Ein DBS macht aber eine ganze Menge mehr, da gibt es gleich einen Cache mit Datensätzen, auf die (vermutlich) demnächst zugegriffen wird. Das heißt, dass nicht die ganze Datei, aber relevante Teile schon im RAM landen. Die benötigte Verdrängungsstrategie, die Datensicherheit, Transaktionen uvm. bringen die meisten (zumindestens die bekannten) dann auch gleich mit. Da kann auf DB2, Oracle, PostgreSql, MySql, MsSql und natürlich Firebird verwiesen werden. Die dürften alle besser skalieren, schneller/effizienter arbeiten, mehr Konsistenz und Sicherheit garantieren als es eine eigene Lösung tut! Da arbeiten einfach viele Leute seit einem Weilchen dran, allein die Nebenläufigkeit dürfte schon ein hartes Stück Arbeit für eine Person sein! Es macht einfach keinen Sinn auf diese (guten!) Lösungen zu gunsten einer eigenen zu verzichten (und sorry, schon gar nicht wenn man dazu einfach versucht alles im Speicher zu halten!).

Harry M. 2. Jul 2007 13:03

Re: Datei > 500mb vollständig in RAM laden
 
Ich geb Dir durchweg Recht, Du angeblich Unwissender :lol:

mkinzler 2. Jul 2007 13:09

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Nimm lieber gleich einen B+/B*-Baum, die können nicht entarten!
Ich hätte wohl hervorheben sollen, daß ich Binärbaum als allgemeinen Oberbegriff ansehe, ob der nun ausbalanziert, gepackt oder wie auch immer implementiert wird.

Der_Unwissende 2. Jul 2007 13:15

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Zitat von mkinzler
Ich hätte wohl hervorheben sollen, daß ich Binärbaum als allgemeinen Oberbegriff ansehe, ob der nun ausbalanziert, gepackt oder wie auch immer implementiert wird.

Nicht falsch verstehen, mir ist schon klar, dass Du nicht unbedingt den normalen Binären-Baum ohne weitere Eigenschaften meinen wirst, wollte nur noch mal explizit darauf hinweisen, welche Bäume üblicherweise sogar verwendet werden. Wie gesagt, die Idee, die Du geäußert hast ist ja auch völlig korrekt und absolut richtig! Das Problem ist doch aber, warum kein DBS einsetzen wollen und sich dann selbst um die Organisation der Datensätze, des Caching (um den Speicher wirklich sinnvoll zu nutzen) und natürlich der Indexierung annehmen?
Klar, ein DBS lädt eben nicht nur den Index in den Speicher, sondern hält auch einzelne Seiten vor, aber das ist ja nicht gerade ein Nachteil. Anders gesagt, wenn man die Funktionalität eines DBS benötigt/nutzen will (und so habe ich Harry M. verstanden), dann ist es manchmal das klügste zu einem DBS zu greifen :wink:

mkinzler 2. Jul 2007 13:21

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Anders gesagt, wenn man die Funktionalität eines DBS benötigt/nutzen will (und so habe ich Harry M. verstanden), dann ist es manchmal das klügste zu einem DBS zu greifen Wink
Klar wurde ihm ja schon von Elvis und mir so gesagt:
Zitat:

Zitat von mkinzler
Aber ich sehe es wie Elvis: Ein solche Lösung würde viel mehr Arbeit als die Einarbeitung in ein DBMS bedeuten und wohl nicht ansatzweise an die Performance herankommen.


alzaimar 2. Jul 2007 16:52

Re: Datei > 500mb vollständig in RAM laden
 
[quote="Elvis"]
Zitat:

Zitat von Harry M.
Jeder (JEDER) Versuch ein eigenes, auf eine spezielle App angepasstes, DBMS zu basteln, der mir bisher unter die Augen kam, war bestenfalls jämmerlich.

Also ich hab mal eine B-Tree-Implementierung zusammengebaut, die ca. 500.000 Schlüssel/Wert-Paare (Schlüssel=String[8], Wert = 64 Byte) speichern und auf der Platte ablegen konnte. Das kann keine richtige DB. Es geht also, wenn man will (War im Rahmen einer Messdatenerfassung von einem CAN-Bus. Der Schlüssel enthielt dabei u.a. Zeit und Kanal-Nummer).

Es gibt mehrere Möglichkeiten, Daten sehr schnell in einem richtigen DBMS abzulegen. Da ich MSSQL verbunden bin, kann ich nur für diese DB sprechen:

Möglichkeit 1 (geht vermutlich für alle DB).
Du sammelst die INSERT-Anweisungen in einem String, bis dieser max. 1000 Zeichen lang ist und bläst diese über die Execute-Methode der ADO-Connection zur DB.

Möglichkeit 2: Du verwendest BCP.EXE (Bluk Copy Program) von Microsoft. Das ist bei jedem Server dabei. Es handelt sich um ein Kommandozeilentool, das speziell formatierte Textdateien sehr schnell (>10000 Recs per second) reinsaugt.

Ich würde #2 nehmen und nur wenn du wirklich Performance brauchst, eine selbstgefrickelte Lösung implementieren. Diese B-Tree-Geschichte war nicht Ohne.

mkinzler 2. Jul 2007 16:59

Re: Datei > 500mb vollständig in RAM laden
 
Als weitere Alternative wären "external files" zu nennen.

alzaimar 2. Jul 2007 17:36

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Zitat von mkinzler
Als weitere Alternative wären "external files" zu nennen.

Was meinst Du damit?

mkinzler 2. Jul 2007 17:41

Re: Datei > 500mb vollständig in RAM laden
 
Das ist eine Funktion von IB/FB, bei der man Textdateien als Tabelle ansprechen kann.

Harry M. 2. Jul 2007 20:02

Re: Datei > 500mb vollständig in RAM laden
 
:mrgreen: Für local Aktionen scheint mir die Sache mit dem Commandozeilentool geeignet. Passt aber nich zum EndZiel meiner Idee.

Ich habe vor Clienten zu einem Server connecten zu lassen, sich dort einen "job" geben zu lassen, diesen berechenen und das Ergebniss zurück zum Server zuschicken. Jetzt greifen mehrere Clienten (mehr oder weniger) gleichzeitig auf den Server holen sich ihre Jobs und tragen die Resulte ein.

Der weg über ADO und eigene FileStreams ist alles nicht passend, hab ich festgestellt wegen der anfallden Datenmege. Also suche ich nach einer Leistungstarken DBMS. Ich denke ein DBMS komprimiert glichzeit. Ich gucke mir grade sie Sache mit IB/FB an. Um ein bisschen mehr Erfahrung zukriegen.

alzaimar 2. Jul 2007 22:05

Re: Datei > 500mb vollständig in RAM laden
 
Zitat:

Zitat von Harry M.
Für local Aktionen scheint mir die Sache mit dem Commandozeilentool geeignet.

bcp.exe (für MSSQL) schiebt die Daten zum Server und passt auf Deine Anwendung. Man kann ja so ein Tool vom Programm aus aufrufen.

Zitat:

Zitat von Harry M.
Ich denke ein DBMS komprimiert glichzeit.

Nein, denn das kostet Zeit.

Zitat:

Zitat von Harry M.
Ich gucke mir grade sie Sache mit IB/FB an. Um ein bisschen mehr Erfahrung zukriegen.

Eine gute Wahl. Klein, kompakt, stark, schnell.

Olli 2. Jul 2007 22:16

Re: Datei > 500mb vollständig in RAM laden
 
Es gibt da ein tolles Buch zum effizienten Umgang mit großen Datenmengen (und anderen tollen Dingen): http://www.cs.bell-labs.com/cm/cs/pearls/

Im Übrigen würde selbst bei 1GiB RAM mit höchster Wahrscheinlichkeit nie die gesamte Datei im Speicher landen. Gut, indirekt in den FS-Cache vielleicht, aber sicher nicht im residenten Speicher der Anwendung. :mrgreen: :mrgreen: :mrgreen:

Habe die Benachrichtigung mal sicherheitshalber ausgeschalten und packe mir auch gleich meinen Asbestanzug aus :stupid:

DelphiProgrammierer 3. Jul 2007 06:33

Re: Datei > 500mb vollständig in RAM laden
 
Ich möchte ergänzen, dass es auch den T-SQL-Befehl BULK INSERT gibt, mit dem man eine Datei importieren kann.


Zitat:

Zitat von alzaimar
Zitat:

Zitat von Harry M.
Jeder (JEDER) Versuch ein eigenes, auf eine spezielle App angepasstes, DBMS zu basteln, der mir bisher unter die Augen kam, war bestenfalls jämmerlich.

Also ich hab mal eine B-Tree-Implementierung zusammengebaut, die ca. 500.000 Schlüssel/Wert-Paare (Schlüssel=String[8], Wert = 64 Byte) speichern und auf der Platte ablegen konnte. Das kann keine richtige DB. Es geht also, wenn man will (War im Rahmen einer Messdatenerfassung von einem CAN-Bus. Der Schlüssel enthielt dabei u.a. Zeit und Kanal-Nummer).

Es gibt mehrere Möglichkeiten, Daten sehr schnell in einem richtigen DBMS abzulegen. Da ich MSSQL verbunden bin, kann ich nur für diese DB sprechen:

Möglichkeit 1 (geht vermutlich für alle DB).
Du sammelst die INSERT-Anweisungen in einem String, bis dieser max. 1000 Zeichen lang ist und bläst diese über die Execute-Methode der ADO-Connection zur DB.

Möglichkeit 2: Du verwendest BCP.EXE (Bluk Copy Program) von Microsoft. Das ist bei jedem Server dabei. Es handelt sich um ein Kommandozeilentool, das speziell formatierte Textdateien sehr schnell (>10000 Recs per second) reinsaugt.

Ich würde #2 nehmen und nur wenn du wirklich Performance brauchst, eine selbstgefrickelte Lösung implementieren. Diese B-Tree-Geschichte war nicht Ohne.



Alle Zeitangaben in WEZ +1. Es ist jetzt 13:08 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