![]() |
AW: Clientdataset Speicherfreigabe
Zitat:
Macht keinen Unterschied. |
AW: Clientdataset Speicherfreigabe
ApplyUpdates + Handler für BeforeApplyUpdates sollte das Delta leeren.
CDS schließen und öffnen. CDS zerstören + neu erzeugen. Ein anderes MemoryDataSet nehmen. Das Problem ignorieren - in der Praxis sollte das doch nicht stören, oder was machst du da? |
AW: Clientdataset Speicherfreigabe
Hab meinen Testcode noch etwas erweitert (erstmal alles, was an Property und Methoden im ClientDataSet zu sehen war, nach dem Delete rein, gesehen es geht und dann schrittweise alles Unnütze wieder raus)
und eine Teillösung gefunden. Es gibt den Speicher nicht komplett frei, aber zumindesten das Log schein weg zu sein. (beim nächsten Add und Delete wird kein neuer Speicher hinzugefügt oder freigegeben)
Delphi-Quellcode:
{$OVERFLOWCHECKS OFF}
uses System.StrUtils, Data.DB, Datasnap.DBClient; 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; CDS.LogChanges := False; for var L := 1 to 199 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'); {$IF false} while CDS.RecordCount > 0 do CDS.Delete; {$ELSE} CDS.EmptyDataSet; {$IFEND} ShowState; except on E: Exception do begin Memo1.Lines.Add(L.ToString + ' : ' + E.Message); ShowState; Break; end; end; end; |
AW: Clientdataset Speicherfreigabe
Zitat:
Die letzten 25 Logeinträge werden dort angezeigt. Bevor der 26.Eintrag geschrieben wird, wird der älteste Eintrag gelöscht. Dabei ist mir das aufgefallen, obwohl ich immer nur 25 Einträge habe läuft der Speicher immer weiter voll. |
AW: Clientdataset Speicherfreigabe
Wenn du nur die Datensätze überschreibst, anstatt zu löschen und neu zu erstellen, dann gibt es kein Problem.
Aber man sollte dringend LogChanges abschalten, denn erstmal bremst das ja ganz extrem und es verbrät dennoch ordentlich Speicher.
Delphi-Quellcode:
{$OVERFLOWCHECKS OFF}
uses System.StrUtils, Data.DB, Datasnap.DBClient; procedure TForm8.FormCreate(Sender: TObject); var CDS: TClientDataSet; Mem: UInt64; procedure ShowState; var GStatus: TMemoryStatusEx; MMState: TMemoryManagerState; begin 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 / %.1nk records / %.1nk changes', [ GStatus.dwMemoryLoad, Int64(GStatus.ullTotalVirtual - GStatus.ullAvailVirtual) / 1048576, IfThen(Mem < GStatus.ullAvailVirtual, '', '+'), Int64(Mem - GStatus.ullAvailVirtual) / 1048576, FastMM / 1048576, CDS.RecordCount / 1000, CDS.ChangeCount / 1000 ])); 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; CDS.LogChanges := False; for var i := 1 to 25 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; for var i := 1 to 100000 do try CDS.RecNo := i mod {25} CDS.RecordCount + 1; CDS.Edit; CDS.FieldByName('TEST1').AsString := Random(MaxInt).ToString; CDS.FieldByName('TEST2').AsString := Random(MaxInt).ToString; CDS.FieldByName('TEST3').AsString := Random(MaxInt).ToString; CDS.Post; if i mod 5000 = 0 then ShowState; except on E: Exception do begin Memo1.Lines.Add(i.ToString + ' : ' + E.Message); ShowState; Break; end; end; ShowState; end; |
AW: Clientdataset Speicherfreigabe
Vielleicht ist ein CDS auch nicht optimal für die Aufgabenstellung. Vielleicht wäre eine simple Liste passender? Oder wenn du es visualisiert haben willst, nimm eine TListBox + füttere dort jeweils 5 Items.
|
AW: Clientdataset Speicherfreigabe
Zitat:
Hätte ich nicht erwartet, da auch andere DataSets von FireDAC oder DevExpress z.B. sich nicht so verhalten. |
AW: Clientdataset Speicherfreigabe
Naja, DevEx und Firedac sind reine InMemory-Datasets + konsolidieren die Änderunggen eben nicht in einem Delta für n-Tier.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:09 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-2025 by Thomas Breitkreuz