Hi all,
I'm struggling with memory management in a GUI created with guide. My MATLAB version is R2014b.
I use guidata to store data in the handles structure to pass large structures (>1 GB) from one function to another inside my GUI.
Inside a Callback function (of a pushbutton), I would like to erase some of those large structures saved in the handles of guidata and create new ones. However, I cannot seem to delete those structures in the function itself. I added the following code in the function:
handles = guidata(hObject);
handles = rmfield(handles, 'my_variable');
guidata(hObject, handles);
But inside the function, the memory is not cleared. I assume it is because the function in which I call this code has hObject and handles as input parameters (it's a callback function...) The "pack" command also has no effect. However, if I debug on these lines and then during function execution quit debugging (so the function stops abruptly), the memory is cleared and my GUI is still open.
So how can I "reset" this guidata while executing a (Callback) function?
I noticed others were struggling with this too, but did not find a solution; e.g. here: https://nl.mathworks.com/matlabcentral/newsreader/view_thread/297824 (last 3 posts)
Thanks in advance! Vincent
Update From Sven's answer in this topic, I assume that after a Callbackfunction is called, the input parameters are actually a copy of the guihandles. So during the Callbackfunction's execution, the same copy is being stored in guihandles. That explains why the memory stays occupied. So how can I obviate that such copy is being made (or remove the variables in the copy as well)?

 採用された回答

Jan
Jan 2016 年 12 月 9 日
編集済み: Jan 2016 年 12 月 9 日

0 投票

How do you control of the memory is released? You can control this on the level of the operating system only.
Removing the field in the handles struct and overwriting the struct in the figure's application data by guidata removes the field efficiently. Afterwards the memory is not occupied anymore, but neither Matlab nor the OS have to give this memory back directly for allocating new arrays. Matlab can keep this memory until it finds time for a garbage collection and the OS will wait with clearing the memory by overwriting it with zeros until one of the processor cores finds the time for this job. Therefore I doubt that you can really determine when the release of the memory exactly happens.
Usually this is not a problem, because the OS cares for cleaning memory with a high precedence if it is getting low on it. Therefore the memory management is usually not a specific problem for users. What exactly is your problem you want to solve?

7 件のコメント

Vincent
Vincent 2016 年 12 月 9 日
編集済み: Vincent 2016 年 12 月 9 日
Thanks for your reply! It already explains a few things.
I simply checked the memory occupied by MATLAB using the command "memory" in debug mode, and via the Windows Task Manager. Both showed the memory was still occupied. When I quit debugging, or the callback exists, the memory is indeed cleared.
I encounter problems in the following:
Step 1. Run some code, store large arrays in the handles, save it with guidata --> all goes fine!
Step 2. The user presses a pushbutton in the GUI. Then the following things should happen in the callback of this pushbutton:
  • Clear previously stored arrays from the handles
  • Create new large arrays via a subfunction --> memory performance issues
  • Store these in the handles via guidata.
When creating these new arrays, I do not have enough RAM memory. Then, MATLAB still works, but gets incredibly slow (50x reduction of speed). I also notice that data is being written to the hard drive.
Btw: I can solve the problem by introducing a new pushbutton to separate step 2-a and step 2-b. I can effectively release the memory via a separate pushbutton, but it seems stupid to always have to push on two buttons after each other...
Vincent
Vincent 2016 年 12 月 13 日
Anybody an idea on how to solve this?
Jan
Jan 2016 年 12 月 16 日
The problem seems to be in the step "clear previously stored arrays from the handles". The "handles" are most likely only a shared data copy of the handles struct provided from the caller. So please explain, if you overwrite the handles struct using guidata before you write new data to it. It might matter also, if you provide the handles struct through the inputs or if you use guidata(hObject) only.
Vincent
Vincent 2016 年 12 月 20 日
Jan, thanks for your reply. Correct, that's the problem. And I suppose I'm working on a copy of the handles as you say.
I get to the handles by calling a pushbutton. Inside the callback of the pushbutton, I tried manipulating the handles. So I'm working under this function:
function push_simulate_Callback(hObject, eventdata, handles)
I then remove the specified fields from the handles (first line in the callback, so I haven't overwritten them yet) using
handles = guidata(hObject);
handles = rmfield(handles, 'my_variable');
guidata(hObject, handles);
So I also update to guidata. But within the same callback, I also create new fields (with the same names, e.g. 'my_variable') and add them to the handles. Then, I get an Out of Memory problem, indicating that the fields from the handles were not cleared initially (because the newly created fields are smaller than the original ones). I also moved the above code to a new subfunction in different two ways (passing the 'handles' as input for one, and getting the handles using guidata in a second approach), but none worked.
I want to do all these operations after activating one pushbutton. As indicated before, using two callbacks obviates this issue and solves the problem: in the first callback, I can remove the fields and store them to guidata. After this callback, I suppose the internal copy is being removed. Then I can activate the second callback to create the fields. This works flawlessly.
I use a workaround now: instead of storing these large matrices/structures in the handles, I save them using setappdata and getappdata. That works fine too, and I can use solely one Callback.
So the problem is solved for me, but others might have troubles with this too.
Walter Roberson
Walter Roberson 2016 年 12 月 20 日
Using setappdata and getappdata is what I would recommend. I do not recommend storing large data in the handles structure, as doing so requires that the data be copied around every time a callback is invoked. getappdata() and setappdata() allows you to retrieve the large data only in the places you actually need it.
Jan
Jan 2016 年 12 月 20 日
I'm used to obtain the "handles" struct (a misleading name) dynamically using guidata, which calls setappdata / getappdata internally also. Therefore "handles struct" and "setappdata" might be exactly the same.
Walter Roberson
Walter Roberson 2016 年 12 月 20 日
setappdata() / getappdata() allows you to give your own name for the item, and so allows you to store and retrieve different parts independently. The handles structure is one particular *appdata item, 'UsedByGUIData_m' in current versions

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

ヘルプ センター および File ExchangeCreating, Deleting, and Querying Graphics Objects についてさらに検索

製品

質問済み:

2016 年 12 月 9 日

コメント済み:

2016 年 12 月 20 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by