Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Antworten
dajackel2012
Beiträge: 8
Registriert: Sa 18. Feb 2012, 00:48
OS, Lazarus, FPC: Winux (L 0.9.30 FPC 2.4.2)
CPU-Target: 32Bit

Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von dajackel2012 »

Hallo!

Ich wollte fragen, ob es mit Lazarus möglich ist, eine DLL zu erstellen, welche über die WinAPI VirtualAlloc (oder ähnlichem) Speicher reserviert und den reservierten
Speicher als Pointer an den Aufrufer zurückgibt. Und wie müsste so eine DLL aussehen?

Mein Problem:
Ich habe eine große Anwendung (Sybase Powerbuilder und nicht mit Lazarus erstellt), welche beim Programmstart 100MB Speicher verbraucht,
nun muss ich eine große Datei ca. 70 bis 200 MB in den Speicher lesen und habe das Problem, dass ich den Speicher nicht in der Größe
reservieren kann, da scheinbar das Speichermanagment in der von mir eingesetzten Programmierumgebung das nicht vorsieht. Meine Idee
ist nun, dass ich über die WinAPI den Speicher reserviere und praktisch an meine Variable übergebe. Um dieses zu machen, benötige ich
allerdings eine DLL, welche ich meine Variable als Referenz übergeben kann, damit diese den Pointer umsetzen kann, da meine Programmierumgebung
von Haus aus nicht direkt mit Pointern umgehen kann, ich aber in der Lage bin an externen Funktionen Variablen als Referenz zu übergeben.
Ich würde dann gedanklich folgendes mit der DLL in meiner Anwendung machen wollen:

Code: Alles auswählen

BLOB lbl_data                                      // Variable deklarieren.
MessageBox("Größe der Variable", len ( lbl_data )) // Hier sollte jetzt 0 rauskommen.
SetVirtualMemory (ref lbl_data, 100)               // Aufruf der DLL Funktion mit der Angabe wie viel Speicher ich haben möchte.
MessageBox("Größe der Variable", len ( lbl_data )) // Hier sollte jetzt ca 104857600 rauskommen.
FreeVirtualMemory(ref lbl_data)                    // Hier sollte der verwendete Speicher wieder freigeben werden.

Ich hoffe ich konnte mein Problem und mein Vorhaben verständlich erläutern und mit ein bißchen Glück kann mir ja jemand
bei der Erstellung so einer DLL helfen.

Grüße
Alex
Programmers don't die, they GOSUB without RETURN

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von Antrepolit »

dajackel2012 hat geschrieben:
Mein Problem:
Ich habe eine große Anwendung (Sybase Powerbuilder und nicht mit Lazarus erstellt), welche beim Programmstart 100MB Speicher verbraucht,
nun muss ich eine große Datei ca. 70 bis 200 MB in den Speicher lesen und habe das Problem, dass ich den Speicher nicht in der Größe
reservieren kann, da scheinbar das Speichermanagment in der von mir eingesetzten Programmierumgebung das nicht vorsieht.


Hast du auch etwas Handfestes? Was genau erzeugt die Fehlermeldung - Windows? Normalerweise ist es gar kein Problem ein paar hunder MB zu reservieren.
Was genau machst du da? Woher kommt die Fehlermeldung? Wilde Spekulationen helfen hier nicht weiter.
Grüße, Antrepolit

care only if your os is really burning

dajackel2012
Beiträge: 8
Registriert: Sa 18. Feb 2012, 00:48
OS, Lazarus, FPC: Winux (L 0.9.30 FPC 2.4.2)
CPU-Target: 32Bit

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von dajackel2012 »

Hallo Antrepolit,
ich habe nur mein Problem geschildert und was ich gerne unternehmen möchte um es zu lösen, deshalb suchte ich hier ja auch Rat. Da ich eine andere Entwicklungsumgebung verwende, kam mir nicht in den Sinn, dass es interessant oder wichtig wäre was ich schon unternommen oder geprüft habe.

Ich habe durch einige Tests herausgefunden, dass bei meiner genutzten Entwicklungsumgebung kein so großer Speicher am Stück reserviert werden kann. In Chunks a 10 MB sind 250 MB kein Problem.

Mein Testsystem:
Windows 7 x64 mit 8GB RAM wobei ca. 21% des Speichers für andere Anwendungen verbraucht ist.
Meine Anwendung (in Powerbuilder 12.5.2511) erstellt verbraucht beim Start 100 MB und wenn damit gearbeitet wird im Schnitt 150MB, wobei der Speicherverbrauch je nachdem was man macht variiert.

Zu meinem Test:
Eine Variable vom Datentyp BLOB (dient für Binärdaten) wird an eine Methode fileReadEx() übergeben, welche eine Datei einließt und den Inhalt in der übergebenen Variable speichert. Das funktioniert bis ca, 50MB reibungslos und wenn ich die Anwendung kompilliere und als exe starte bis 70 MB zuverlässig. Bei größeren Dateien bekommt man die Meldung " Memory is not enough! at
line .... "

Laut Dokumentation des Herstellers können BLOBs aber bis zu 2 GB Daten enthalten.

Test 2: Kleine Minianwendung anstatt der großen Anwendung
Eine neue Anwendung, nur ein Fenster mit einem Button was genau das gleiche macht schafft das Einlesen einer 90 MB Datei drei Mal zuverlässig. Manchmal auch vier Mal, aber öfters nur drei Mal anstatt der viere.

Test 3: Aufteilen in viele kleine Blobs
Anstatt nur eine BLOB Variable zu deklarieren habe ich ein Array vom Typ BLOB genommen. Damit schaffe ich es eine 250 MB Datei problemlos einzulesen. Aber halt nur in Stücken a 10 MB. Wenn ich mehr einlese bekomme ich auch dort später die Fehlermeldung oder ein Programmabsturz.

Test 4: Aufteilen in viele kleine Blobs in einer Minianwendung.
Hier konnte ich die Datei drei Mal einlesen und beim vierten Mal stürzt die Anwendung bei ca. 900 MB RAM ab.

Meine Vermutung: Es steht einem in meiner Entwicklungsumgebung nur begrenzt Speicher zu Verfügung und dieser scheint "fragmentiert" zu sein, so dass es nicht möglich ist großen Speicher am Stück zu reservieren. Anders kann ich mir nicht erklären, warum eine Minianwendung es schafft Blobs bis zu einem Verbrauch von 900MB zu reservieren und meine große Anwendung schon bei nicht einmal 200 MB RAM abstürzt oder die Fehlermeldung bringt.

Alle Tests habe ich übrigens auch ohne das Einlesen einer Datei getestet indem ich den oder die Variablen einfach mit Leerzeichen initialisiert habe.

Ich hoffe Antrepolit, dass ich dich damit zufriedenstellen konnte. :-)
Programmers don't die, they GOSUB without RETURN

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von Antrepolit »

Das Problem solltest du an der richtigen Stelle beheben. Eine DLL, die Speicher reserviert ist Gefrickel, und es funktioniert auch nicht. DEnn das Problem ist die andere IDE.
Powerbuilder ist wohl so eine .NET-Geschichte. Bei .NET ist die Speicherfragmentierung ein bekanntes Problem. Bisher sieht Microsoft dort aber keinen Handlungsbedarf.
Grüße, Antrepolit

care only if your os is really burning

carli
Beiträge: 657
Registriert: Sa 9. Jan 2010, 17:32
OS, Lazarus, FPC: Linux 2.6.x, SVN-Lazarus, FPC 2.4.0-2
CPU-Target: 64Bit

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von carli »

Gerade bei solchen Problemen ist es eben keine Pascal-Frage mehr, sondern eine Frage der benutzten Umgebung. Freepascal ist ein nativer Compiler, während das .NET-Zeugs alles managed ist.

dajackel2012
Beiträge: 8
Registriert: Sa 18. Feb 2012, 00:48
OS, Lazarus, FPC: Winux (L 0.9.30 FPC 2.4.2)
CPU-Target: 32Bit

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von dajackel2012 »

Nein, das ist falsch. Es gibt PB Classic (das was ich einsetze) und PB.NET, was praktisch eine Art .NET Sprache ist. In Classic gibt es nichts was mit .NET zu tun hat, es sei denn, man macht ein Assembly ComVisible und somit zu einer Art OLEObjekt.

Das mit der DLL sollte nur den Umstand umgehen, dass ich einen Pointer wie man ihn mit den VirtualAlloc Methoden bekommt nicht einer Variable zuweisen kann. Aber ich kann einer externen Funktion (DLL) eine Variable als Referenz übergeben wodurch die DLL ja diese Neuzuweisung durchführen könnte. So war zumindest mein Gedanke.
Programmers don't die, they GOSUB without RETURN

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von Antrepolit »

Wenn das nicht .NET ist, dann ist es Java, da der PowerDesigner auch auf Java basiert. Und Java-Anwendungen kann man per Parameter mitgeben, wieviel Arbeitsspeicher sie belegen dürfen. Dass eine Java-Anwendung gewiss nicht direkt mit DLLs und dem Windows Speichermanager hantiert, dürfte klar sein.

Der Parameter -Xmx2G beim Starten der IDE sollte helfen.
Grüße, Antrepolit

care only if your os is really burning

dajackel2012
Beiträge: 8
Registriert: Sa 18. Feb 2012, 00:48
OS, Lazarus, FPC: Winux (L 0.9.30 FPC 2.4.2)
CPU-Target: 32Bit

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von dajackel2012 »

Nein, es ist nicht Java, aber es ist eine Art VM im Background welche allerdings von Sybase selbst geschrieben wurde. Diese arbeitet auch mit einem eigenen Speichermanagement wie ich inzwischen erfahren habe.

Die eigentliche Frage "Wie erstelle ich so eine DLL..." ist aber immer noch unbeantwortet.
Programmers don't die, they GOSUB without RETURN

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von Antrepolit »

dajackel2012 hat geschrieben:Nein, es ist nicht Java, aber es ist eine Art VM im Background welche allerdings von Sybase selbst geschrieben wurde. Diese arbeitet auch mit einem eigenen Speichermanagement wie ich inzwischen erfahren habe.
(...)


Nunja, da die VM von Sybase schon nicht genug Speicher bei Windows anfragt, verstehe ich auch nicht, wie sie dies denn tun sollte, selbst wenn sie mehr bekäme. Wie kann dir so eine DLL also helfen?

dajackel2012 hat geschrieben:Meine Idee ist nun, dass ich über die WinAPI den Speicher reserviere und praktisch an meine Variable übergebe. Um dieses zu machen, benötige ich
allerdings eine DLL, welche ich meine Variable als Referenz übergeben kann, damit diese den Pointer umsetzen kann, da meine Programmierumgebung von Haus aus nicht direkt mit Pointern umgehen kann, (...)

Da hast du schlechte Karten. In der Windows API und bei DLLs läuft eigentlich alles über Pointer. Evtl. solltest du auch mal nach der richtigen Lösung suchen. Sybase hatte ja nun Gründe, eine eigene VM im Hintergrund laufen zu lassen und so etwas ist bestimmt kein Einzelfall. Hättest du genug Speicher könnte deine Anwendung damit vermutlich auch wieder nicht umgehen - wenn sie es könnte, hätte sie es ja getan.
Grüße, Antrepolit

care only if your os is really burning

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von Antrepolit »

Hast du dir das hier überhaupt mal durchgelesen?
http://www.sybase.de/detail?id=1027319#tuning
Grüße, Antrepolit

care only if your os is really burning

dajackel2012
Beiträge: 8
Registriert: Sa 18. Feb 2012, 00:48
OS, Lazarus, FPC: Winux (L 0.9.30 FPC 2.4.2)
CPU-Target: 32Bit

Re: Speicher in einer DLL reservieren und weitergeben (WinAPI Vi

Beitrag von dajackel2012 »

Moin,
hab da jetzt einen Bugreport aufgemacht. Und ja diese Umgebungsvariablen habe ich schon ausprobiert. Bringen jedoch nicht viel, da sie her für den EA Server (eine Art Applicationserver) gedacht sind. Aber trotzdem lieb von dir, dass du das ergoogelt hast.
Programmers don't die, they GOSUB without RETURN

Antworten