![]() |
Clientdataset Speicherfreigabe
Hallo zusammen,
wieso wird beim TClientdataset der Speicher nicht freigegeben wenn man Datensätze löscht? Muss ich da noch irgendetwas auslösen? Beim TFDMemTable wird der Speicher direkt nach dem löschen wieder freigegeben.
Delphi-Quellcode:
unit Unit121;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Datasnap.DBClient, Vcl.StdCtrls, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.Comp.DataSet, FireDAC.Comp.Client; type TForm121 = class(TForm) gb_clientdataset: TGroupBox; b_clientdataset_add: TButton; b_clientdataset_delete: TButton; l_clientdataset: TLabel; gb_fdmemtable: TGroupBox; l_fdmemtable: TLabel; b_fdmemtable_add: TButton; b_fdmemtable_delete: TButton; procedure b_clientdataset_addClick(Sender: TObject); procedure b_clientdataset_deleteClick(Sender: TObject); procedure b_fdmemtable_addClick(Sender: TObject); procedure b_fdmemtable_deleteClick(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } lClientDataSet: TClientDataSet; lFDMemTable: TFDMemTable; procedure Add( xDataset: TDataSet; xLabel: TLabel); procedure Delete( xDataset: TDataSet; xLabel: TLabel); end; var Form121: TForm121; implementation {$R *.dfm} procedure TForm121.Add(xDataset: TDataSet; xLabel: TLabel); begin for var i := 1 to 9999 do begin xDataset.Append; xDataset.FieldByName('TEST1').AsString := Random( MaxInt).ToString; xDataset.FieldByName('TEST2').AsString := Random( MaxInt).ToString; xDataset.FieldByName('TEST3').AsString := Random( MaxInt).ToString; xDataset.Post; end; xLabel.Caption := Format( 'Recordcount: %d', [ xDataset.RecordCount]); end; procedure TForm121.b_clientdataset_addClick(Sender: TObject); begin Add( lClientDataSet, l_clientdataset); end; procedure TForm121.b_clientdataset_deleteClick(Sender: TObject); begin Delete( lClientDataSet, l_clientdataset); end; procedure TForm121.b_fdmemtable_addClick(Sender: TObject); begin Add( lFDMemTable, l_fdmemtable); end; procedure TForm121.b_fdmemtable_deleteClick(Sender: TObject); begin Delete( lFDMemTable, l_fdmemtable); end; procedure TForm121.Delete(xDataset: TDataSet; xLabel: TLabel); begin while ( xDataset.RecordCount > 0) do begin xDataset.Delete; end; xLabel.Caption := Format( 'Recordcount: %d', [ xDataset.RecordCount]); end; procedure TForm121.FormCreate(Sender: TObject); begin Randomize; lClientDataSet := TClientDataSet.Create( Self); lClientDataSet.FieldDefs.Add( 'TEST1', ftString, 500); lClientDataSet.FieldDefs.Add( 'TEST2', ftString, 500); lClientDataSet.FieldDefs.Add( 'TEST3', ftString, 500); lClientDataSet.CreateDataSet; lFDMemTable := TFDMemTable.Create( Self); lFDMemTable.FieldDefs.Add( 'TEST1', ftString, 500); lFDMemTable.FieldDefs.Add( 'TEST2', ftString, 500); lFDMemTable.FieldDefs.Add( 'TEST3', ftString, 500); lFDMemTable.CreateDataSet; end; end. |
AW: Clientdataset Speicherfreigabe
Hast du es mal mit MergeChangeLog probiert?
|
AW: Clientdataset Speicherfreigabe
Zitat:
Wenn ich nur an einer stelle Insert oder Delete MergeChangeLog ausführe wächst die Auslastung bei jedem neuen Insert. LogChanges hilft auch nicht. |
AW: Clientdataset Speicherfreigabe
Welcher Speicher wächst?
Ich tippe mal auf eine Speicherfragmentierung im FastMM. Was sagt denn GetMemoryManagerState? Hat ein billiges ClientDataSet überhaupt ein ChangeLog? |
AW: Clientdataset Speicherfreigabe
Zitat:
Clientdataset
FDMemTable
Was sagt denn GetMemoryManagerState? - Da steht immer das selbe hättest du da ein Beispiel wie ich das richtig anwende bzw. was möchtest du da genau sehen? Beim dxMemTable von DevExpress wird der Speicher auch freigegeben. Wenn ich bei einer TList oder TObjectList Einträge entferne werden die auch direkt freigegeben. Ich hab das Problem nur bei TClientDataSets |
AW: Clientdataset Speicherfreigabe
Liste der Anhänge anzeigen (Anzahl: 1)
Hier nochmal das komplette Testprojekt.
|
AW: Clientdataset Speicherfreigabe
Die scheinen den Speicher direkt bei Windows zu reservieren.
Hmmm, im FastMM steigt nichts an. Aber im Code (Datasnap.DBClient) finde ich nur ein AllocMem, was eigentlich im Delphi-MemoryManager (FastMM) landen sollte. :gruebel: Ich komm nach genügend Durchläufen (Add+Delete) sogar in einen OutOfMemory.
Delphi-Quellcode:
procedure TForm8.FormCreate(Sender: TObject);
var CDS: TClientDataSet; Mem: UInt64; procedure ShowState; var GStatus: TMemoryStatusEx; MMState: TMemoryManagerState; begin //Memo1.Lines.Add(' Records ' + CDS.RecordCount.ToString); GStatus.dwLength := SizeOf(GStatus); GlobalMemoryStatusEx(GStatus); GetMemoryManagerState(MMState); var FastMM: Int64 := 0; for var i := 0 to High(MMState.SmallBlockTypeStates) do Inc(FastMM, MMState.SmallBlockTypeStates[i].UseableBlockSize * MMState.SmallBlockTypeStates[i].AllocatedBlockCount); Inc(FastMM, MMState.TotalAllocatedMediumBlockSize); Inc(FastMM, MMState.TotalAllocatedLargeBlockSize); Memo1.Lines.Add(Format(' Memory %d%% %.2nm %s%.2nm / %.2nm', [ GStatus.dwMemoryLoad, Int64(GStatus.ullTotalVirtual - GStatus.ullAvailVirtual) / 1048576, IfThen(Mem < GStatus.ullAvailVirtual, '', '+'), Int64(Mem - GStatus.ullAvailVirtual) / 1048576, FastMM / 1048576 ])); Mem := GStatus.ullAvailVirtual; end; begin Mem := 0; CDS := TClientDataSet.Create(Self); CDS.FieldDefs.Add('TEST1', ftString, 500); CDS.FieldDefs.Add('TEST2', ftString, 500); CDS.FieldDefs.Add('TEST3', ftString, 500); CDS.CreateDataSet; for var L := 1 to 99 do try Memo1.Lines.Add(L.ToString); //Memo1.Lines.Add('Add'); for var i := 1 to 9999 do begin CDS.Append; CDS.FieldByName('TEST1').AsString := Random(MaxInt).ToString; CDS.FieldByName('TEST2').AsString := Random(MaxInt).ToString; CDS.FieldByName('TEST3').AsString := Random(MaxInt).ToString; CDS.Post; end; ShowState; //Memo1.Lines.Add('Delete'); while CDS.RecordCount > 0 do CDS.Delete; ShowState; except on E: Exception do begin Memo1.Lines.Add(L.ToString + ' : ' + E.Message); ShowState; Break; end; end; end; |
AW: Clientdataset Speicherfreigabe
Vielleicht ist es nicht jedem bewusst, aber die DB-Engine des TClientDataset liegt in der Midas.dll bzw. ihrem eingelinkten binären Zwilling. Damit arbeitet es schon etwas anders als die reine Delphi-Implementierung von FireDAC.
|
AW: Clientdataset Speicherfreigabe
Die ClientDataSets sind ja eigentlich für n-tier Anwendungen gemacht, hängen also an einem Provider, der die das Änderungslog (DELTA) weiterreicht. Ein DELETE löscht also nicht wirklich, sondern hebt alles auf, was notwendig ist, um die Änderung weiterreichen zu können UND um das Löschen auch rückgängig machen zu können. Siehe "CancelUpdates".
Es überrascht mich also nicht, dass Speicher alloziert bleibt. Jedes Feld gibt es im CDS 3x: newValue/Value/oldValue - da kommt im Code unten schon (unrealistischerweise) was zusammen: 99 x 9999 x 3 x 3 x 500 Mit dem Zerstören des CDS wird dann auch der Speicher freigegeben. |
AW: Clientdataset Speicherfreigabe
Einfach mal nach "CreateDataSet" die Property "LogChanges" auf false setzen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz