Wir haben eine D2007-Anwendung, deren Speicherbedarf bei der Ausführung auf Windows Server 2008 (x64, sp1) stetig wächst.
Es verhält sich normal auf Windows Server 2003 (x32 oder x64), XP, etc... wo es hoch und runter geht wie erwartet.
Wir haben es mit dem mitgelieferten Memory Manager oder dem neuesten FastMM4 4.92 versucht, mit den gleichen Ergebnissen.
Hat jemand versucht, die Speichernutzung einer Delphi-Anwendung auf Win2008 zu überwachen und kann dies bestätigen?
Oder hätten Sie eine Ahnung?
Genaue Angaben:
- keine Speicherlecks im üblichen Sinne (und ja, ich bin mit FastMM und Co. gut vertraut)
- Die Speichernutzung wurde mit Process Explorer überwacht; sowohl der virtuelle Speicher (private Bytes) als auch der physische Speicher (WorkingSet Private) wachsen unter Win2008
- Der Speicherverbrauch stieg auch dann noch an, wenn der Speicherplatz knapp war. (so kamen wir zu der Untersuchung, da es einen Fehler verursachte, aber nur auf Win2008-Boxen)
Update : Der //** repaced **// Code ist viel einfacher als unsere Anwendung, zeigt aber das gleiche Verhalten.
Das Erstellen einer Liste mit 10.000.000 Objekten und dann 10.000.000 Schnittstellen, die 2 Mal ausgeführt wird, erhöht den verwendeten Speicher um ~60 MB und um etwa 300 MB für 100 weitere Ausführungen auf Windows Server 2008, kehrt aber gerade zu dem Wert zurück, der unter XP bestand.
Wenn Sie mehrere Instanzen starten, wird der Speicher nicht freigegeben, damit die anderen Instanzen ausgeführt werden können. Stattdessen wächst die Auslagerungsdatei und der Server kriecht...
Aktualisierung 2 : siehe QC-Bericht 73347
Nach weiteren Untersuchungen haben wir hat es auf kritische Abschnitte zurückgeführt wie im nachstehenden Code gezeigt.
Fügen Sie diesen Code in eine einfache VCL-Anwendung mit einer Schaltfläche ein. Und überwachen Sie mit Process Explorer:
Es beginnt mit ~2,6 MB und nach 5 Durchläufen (Klicks auf die Schaltfläche) bleibt es bei ~118,6 MB.
116 MB in 5 Ausführungen verloren.
//***********************
const
CS_NUMBER = 10000000;
type
TCSArray = Array[1..CS_NUMBER] of TRTLCriticalSection;
PCSArray = ^TCSArray;
procedure TestStatic;
var
csArray: PCSArray;
idx: Integer;
begin
New(csArray);
for idx := 1 to length(csArray^) do
InitializeCriticalSection(csArray^[idx]);
for idx := 1 to length(csArray^) do
DeleteCriticalSection(csArray^[idx]);
Dispose(csArray);
end;
procedure TestDynamic(const Number: Integer);
var
csArray: array of TRTLCriticalSection;
idx: Integer;
begin
SetLength(csArray, Number);
for idx := Low(csArray) to High(csArray) do
InitializeCriticalSection(csArray[idx]);
for idx := Low(csArray) to High(csArray) do
DeleteCriticalSection(csArray[idx]);
end;
procedure TForm4.Button1Click(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown := True;
TestStatic;
TestDynamic(CS_NUMBER);
end;