Speicherfreigabe bei Listen
-
fabulouspaul
- Beiträge: 120
- Registriert: 01.04.2011 21:59
Speicherfreigabe bei Listen
Hallo zusammen,
ich bastle gerade etwas herum, um bestimmte Informationen mit einem "Zeitstempel" in einer Queue zu verwalten. Nach einer gewissen Zeit soll die Information ungültig werden und aus der Queue gelöscht werden.
Ich habe mir eine Struktur mit den nötigen Datentypen angelegt und mit NewList() eine entsprechende Liste erzeugt.
Jede Sekunde wird nun die Liste durchgeschaut, ob Elemente gelöscht werden können (DeleteElement()).
Wenn ich mir den Taskmanager dazunehme, wächst die Liste zwar mit den neuen Elementen jeweils an, aber der Speicherplatz wird nach dem Löschen nicht wieder freigegeben. Selbst wenn alle Elemente mit DeleteElement() gelöscht wurden, bleibt der Speicherverbrauch konstant. Wenn dann wieder ein Element hinzugefügt wird, wird erneut Speicher verbraucht, so dass irgendwann der Speicher vollläuft.
Mache ich was falsch oder ist das einfach so?
Grüße Paul
ich bastle gerade etwas herum, um bestimmte Informationen mit einem "Zeitstempel" in einer Queue zu verwalten. Nach einer gewissen Zeit soll die Information ungültig werden und aus der Queue gelöscht werden.
Ich habe mir eine Struktur mit den nötigen Datentypen angelegt und mit NewList() eine entsprechende Liste erzeugt.
Jede Sekunde wird nun die Liste durchgeschaut, ob Elemente gelöscht werden können (DeleteElement()).
Wenn ich mir den Taskmanager dazunehme, wächst die Liste zwar mit den neuen Elementen jeweils an, aber der Speicherplatz wird nach dem Löschen nicht wieder freigegeben. Selbst wenn alle Elemente mit DeleteElement() gelöscht wurden, bleibt der Speicherverbrauch konstant. Wenn dann wieder ein Element hinzugefügt wird, wird erneut Speicher verbraucht, so dass irgendwann der Speicher vollläuft.
Mache ich was falsch oder ist das einfach so?
Grüße Paul
Re: Speicherfreigabe bei Listen
Ohne Code lässt sich da wenig sagen. Normalerweise allokiert PB einen Speicherbereich für eine Liste, in dem über 1000 Elemente oder so gespeichert werden können. Dieser wird nur dann vergrößert, wenn man mehr Elemente reinhaut. Wenn Elemente gelöscht werden, ist in diesem Speicherbereich wieder Platz frei. Der Speicher selbst wird aber nicht freigegeben. Allerdings sollte nicht nochmal Speicher allokiert werden, wenn man dann in die leere Liste Elemente reintut.
Also scheint da was nicht zu stimmten. Allokierst du selbst mit AllocateMemory Speicher? Irgendein verpfuschen von Strings wäre auch noch denkbar. Aber wie gesagt, ohne Code keine Möglichkeit zu helfen.
lg Kevin
Also scheint da was nicht zu stimmten. Allokierst du selbst mit AllocateMemory Speicher? Irgendein verpfuschen von Strings wäre auch noch denkbar. Aber wie gesagt, ohne Code keine Möglichkeit zu helfen.
lg Kevin

http://www.jasik.de - Windows Hilfe Seite
padawan hat geschrieben:Ich liebe diese von hinten über die Brust ins Auge Lösungen
-
fabulouspaul
- Beiträge: 120
- Registriert: 01.04.2011 21:59
Re: Speicherfreigabe bei Listen
Ich allokiere keinen Speicher über die Memory-Befehle, es läuft alles über die Liste.
Hier mein (etwas unaufgeräumter) Code:
Man kann am Taskmanager gut verfolgen wie mit jedem hinzufügen eines Elements der belegte Speicher steigt, wenn Elemente rausfallen wird der Speicherbedarf nicht geringer. Das wäre auch OK, wenn der Speicherbedarf dann konstant bliebe wenn nach dem Löschen neue Elemente hinzukommen...
Hier mein (etwas unaufgeräumter) Code:
Code: Alles auswählen
EnableExplicit
;- Window Constants
;
Enumeration
#Main_Window
EndEnumeration
;- Gadget Constants
;
Enumeration
#Button_0
#Button_1
#Frame3D_0
#ListIcon_1
EndEnumeration
;- StatusBar Constants
;
Enumeration
#StatusBar_1
EndEnumeration
Procedure Open_Main_Window()
If OpenWindow(#Main_Window, 364, 223, 583, 555, "Queue-Spielerei", #PB_Window_SystemMenu | #PB_Window_TitleBar )
If CreateStatusBar(#StatusBar_1, WindowID(#Main_Window))
AddStatusBarField(380)
AddStatusBarField(200)
StatusBarText(#StatusBar_1, 0, "")
StatusBarText(#StatusBar_1, 1, "")
EndIf
If CreateGadgetList(WindowID(#Main_Window))
ButtonGadget(#Button_0, 470, 0, 110, 30, "Ende")
ButtonGadget(#Button_1, 0, 0, 110, 30, "Element hinzufügen")
Frame3DGadget(#Frame3D_0, 0, 40, 580, 490, "Queue-Inhalt")
;-
ListIconGadget(#ListIcon_1, 10, 60, 562, 460, "IP-Adresse", 100, #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect)
AddGadgetColumn(#ListIcon_1, 1, "Port", 50)
AddGadgetColumn(#ListIcon_1, 2, "Client-Name", 120)
AddGadgetColumn(#ListIcon_1, 3, "Client-Typ", 100)
AddGadgetColumn(#ListIcon_1, 4, "Token", 80)
AddGadgetColumn(#ListIcon_1, 5, "Letzter Kontakt", 90)
EndIf
EndIf
EndProcedure
Structure queue ; Struktur der Queue
IPAdresse.s ; IP-Adresse des Clients
Port.i ; Port des Clients
Clientname.s ; Name des Clients
Clienttype.i ; Art des Clients (1 = Supplier, 2 = Worker)
Clienttoken.i ; ID-Token des Clients
Lastcontact.i ; Letztes "Lebenssignal" des Clients
EndStructure
Global NewList client.queue() ; Client-Queue anlegen
Global Dim clienttyp.s(2) ; Klarschrift des Client-Typs
Global alive ; Zeit in Sek. in der der Client ein Lebenssignal abgeben muss
Global Event, WindowID, GadgetID, EventType
Global exitloop
Declare init()
Declare refresh_list()
Declare delete_outdated()
Open_Main_Window()
init()
exitloop = 0
Repeat ; Start of the event loop
Event = WaitWindowEvent(1000) ; Auf einen Windows-Event warten oder nach 1 Sek. weitermachen
WindowID = EventWindow() ; Aus welchem Fenster kommt der Event?
GadgetID = EventGadget() ; Ist es ein gadget-Event?
EventType = EventType() ; Was ist es für ein Event-Typ?
If delete_outdated() = 1 ; Abgelaufene Einträge entfernen
refresh_list() ; ...und wenn Einträge entfernt wurden, Listenanzeige auffrischen
EndIf
If Event = #PB_Event_Gadget
If GadgetID = #Button_1 ; Eintrag hinzufügen
AddElement(client())
client()\IPAdresse = Right("000" + Str(Random(255)),3) + "." + Right("000" + Str(Random(255)),3) + "." + Right("000" + Str(Random(255)),3) + "." + Right("000" + Str(Random(255)),3)
client()\Port = Random(65535)
client()\Clientname = "Test_" + Str(ListSize(client()))
client()\Clienttype = Random(2)
client()\Clienttoken = Random(9999999999)
client()\Lastcontact = Date()
refresh_list() ; Listenanzeige auffrischen
ElseIf GadgetID = #Button_0 ; Ende
exitloop = 1
EndIf
EndIf
Until Event = #PB_Event_CloseWindow Or exitloop = 1 ; End of the event loop
End
Procedure init()
clienttyp(0) = "*undefiniert*"
clienttyp(1) = "Supplier"
clienttyp(2) = "Worker"
alive = 10
EndProcedure
Procedure refresh_list()
ClearGadgetItems(#ListIcon_1)
FirstElement(client())
ForEach client()
AddGadgetItem(#ListIcon_1, -1, client()\IPAdresse + Chr(10) + Str(client()\Port) + Chr(10) + client()\Clientname + Chr(10) + clienttyp(client()\Clienttype) + Chr(10) + Str(client()\Clienttoken) + Chr(10) + Str(client()\Lastcontact))
Next
StatusBarText(#StatusBar_1, 0, Str(ListSize(client())))
EndProcedure
Procedure delete_outdated()
Protected action
action = 0
FirstElement(client())
ForEach client()
If Date() > client()\Lastcontact + alive
DeleteElement(client())
action = 1
EndIf
Next
ProcedureReturn action
EndProcedure
Re: Speicherfreigabe bei Listen
Ob es mit meiner Methode sinnvoll ist, weiß ich zwar nicht, aber du könntest dafür sorgen, dass Windows dein Speicher bereinigt (WinAPI):
Code: Alles auswählen
EnableExplicit
;- Window Constants
;
Enumeration
#Main_Window
EndEnumeration
;- Gadget Constants
;
Enumeration
#Button_0
#Button_1
#Button_2
#Frame3D_0
#ListIcon_1
EndEnumeration
;- StatusBar Constants
;
Enumeration
#StatusBar_1
EndEnumeration
Procedure freeWorkingMemory()
Protected myProcessID,PHandle,Result
myProcessID=GetCurrentProcessId_()
PHandle = GetCurrentProcess_()
Result= SetProcessWorkingSetSize_(PHandle,-1,-1)
If Result
Else
; it failed
EndIf
EndProcedure
Procedure Open_Main_Window()
If OpenWindow(#Main_Window, 364, 223, 583, 555, "Queue-Spielerei", #PB_Window_SystemMenu | #PB_Window_TitleBar )
If CreateStatusBar(#StatusBar_1, WindowID(#Main_Window))
AddStatusBarField(380)
AddStatusBarField(200)
StatusBarText(#StatusBar_1, 0, "")
StatusBarText(#StatusBar_1, 1, "")
EndIf
If CreateGadgetList(WindowID(#Main_Window))
ButtonGadget(#Button_0, 470, 0, 110, 30, "Ende")
ButtonGadget(#Button_1, 0, 0, 110, 30, "Element hinzufügen")
ButtonGadget(#Button_2, 200, 0, 110, 30, "Speicher bereinigen")
Frame3DGadget(#Frame3D_0, 0, 40, 580, 490, "Queue-Inhalt")
;-
ListIconGadget(#ListIcon_1, 10, 60, 562, 460, "IP-Adresse", 100, #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect)
AddGadgetColumn(#ListIcon_1, 1, "Port", 50)
AddGadgetColumn(#ListIcon_1, 2, "Client-Name", 120)
AddGadgetColumn(#ListIcon_1, 3, "Client-Typ", 100)
AddGadgetColumn(#ListIcon_1, 4, "Token", 80)
AddGadgetColumn(#ListIcon_1, 5, "Letzter Kontakt", 90)
EndIf
EndIf
EndProcedure
Structure queue ; Struktur der Queue
IPAdresse.s ; IP-Adresse des Clients
Port.i ; Port des Clients
Clientname.s ; Name des Clients
Clienttype.i ; Art des Clients (1 = Supplier, 2 = Worker)
Clienttoken.i ; ID-Token des Clients
Lastcontact.i ; Letztes "Lebenssignal" des Clients
EndStructure
Global NewList client.queue() ; Client-Queue anlegen
Global Dim clienttyp.s(2) ; Klarschrift des Client-Typs
Global alive ; Zeit in Sek. in der der Client ein Lebenssignal abgeben muss
Global Event, WindowID, GadgetID, EventType
Global exitloop
Declare init()
Declare refresh_list()
Declare delete_outdated()
Open_Main_Window()
init()
exitloop = 0
Repeat ; Start of the event loop
Event = WaitWindowEvent(1000) ; Auf einen Windows-Event warten oder nach 1 Sek. weitermachen
WindowID = EventWindow() ; Aus welchem Fenster kommt der Event?
GadgetID = EventGadget() ; Ist es ein gadget-Event?
EventType = EventType() ; Was ist es für ein Event-Typ?
If delete_outdated() = 1 ; Abgelaufene Einträge entfernen
refresh_list() ; ...und wenn Einträge entfernt wurden, Listenanzeige auffrischen
EndIf
If Event = #PB_Event_Gadget
If GadgetID = #Button_1 ; Eintrag hinzufügen
AddElement(client())
client()\IPAdresse = Right("000" + Str(Random(255)),3) + "." + Right("000" + Str(Random(255)),3) + "." + Right("000" + Str(Random(255)),3) + "." + Right("000" + Str(Random(255)),3)
client()\Port = Random(65535)
client()\Clientname = "Test_" + Str(ListSize(client()))
client()\Clienttype = Random(2)
client()\Clienttoken = Random(9999999999)
client()\Lastcontact = Date()
refresh_list() ; Listenanzeige auffrischen
ElseIf GadgetID = #Button_0 ; Ende
exitloop = 1
ElseIf GadgetID = #Button_2
freeWorkingMemory()
EndIf
EndIf
Until Event = #PB_Event_CloseWindow Or exitloop = 1 ; End of the event loop
End
Procedure init()
clienttyp(0) = "*undefiniert*"
clienttyp(1) = "Supplier"
clienttyp(2) = "Worker"
alive = 10
EndProcedure
Procedure refresh_list()
ClearGadgetItems(#ListIcon_1)
FirstElement(client())
ForEach client()
AddGadgetItem(#ListIcon_1, -1, client()\IPAdresse + Chr(10) + Str(client()\Port) + Chr(10) + client()\Clientname + Chr(10) + clienttyp(client()\Clienttype) + Chr(10) + Str(client()\Clienttoken) + Chr(10) + Str(client()\Lastcontact))
Next
StatusBarText(#StatusBar_1, 0, Str(ListSize(client())))
EndProcedure
Procedure delete_outdated()
Protected action
action = 0
FirstElement(client())
ForEach client()
If Date() > client()\Lastcontact + alive
DeleteElement(client())
action = 1
EndIf
Next
ProcedureReturn action
EndProcedure-
fabulouspaul
- Beiträge: 120
- Registriert: 01.04.2011 21:59
Re: Speicherfreigabe bei Listen
Hmmm, ist nicht ganz da, was ich mir vorgestellt habe, aber die Speicherbereinigung über die API sieht doch erstmal gut aus!
Wenn ich nicht manuell bereinige, sondern immer dann, wenn Elemente aus der Liste gelöscht wurden, dann sollte der Speicher eigentlich nicht voll laufen.
Prima, das hilft mir!
DANKE!
Wenn ich nicht manuell bereinige, sondern immer dann, wenn Elemente aus der Liste gelöscht wurden, dann sollte der Speicher eigentlich nicht voll laufen.
Prima, das hilft mir!
DANKE!
Re: Speicherfreigabe bei Listen
Ich kann die Speicherzumüllung übrigens nicht bestätigen. Die Speicheranzeige ist ja ein bisschen träge. Wenn man da ein bisschen wartet, geht der Verbrauch auch wieder zurück. Zumindest bei mir.
lg Kevin
lg Kevin

http://www.jasik.de - Windows Hilfe Seite
padawan hat geschrieben:Ich liebe diese von hinten über die Brust ins Auge Lösungen
Re: Speicherfreigabe bei Listen
Das hört sich nach dem gleichen "Problem" an, wie es hier beschrieben wurde: http://www.purebasic.fr/english/viewtop ... 13&t=50449
Grüße, Ninofreak hat geschrieben:Never trust programs like the task manager about such things. As long as there is no immediate need for the freed memory, the OS will usually keep it reserved for the program for a possible later allocation. So the number doesn't go down immediately. That doesn't mean that the memory is actually still allocated by the program.
Re: Speicherfreigabe bei Listen
Sinngemäß übersetzt heißt das, das du die Linked Liste ruhig benutzen
kannst und dir nichts darauf geben solltest, was Windows im Task Manager
zeigt.
MFG PMV
kannst und dir nichts darauf geben solltest, was Windows im Task Manager
zeigt.
MFG PMV

