Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Memory leak within actor updating IMAQ image control by reference

I have a serious memory leak within my application that utilizes the actor framework to handle instrumentation. I have narrowed down the memory leak to simply passing an IMAQ image reference to the "Value" property for an IMAQ ImageControl (using a reference property node). If I disable this property node, the memory leak disappears. The memory leak is severe and reaches the 3GB limit in about 30 seconds or so. However, once I hit okay on the "Not enough memory to complete this operation" dialog, LabVIEW's memory lowers to normal values (watching via task manager) and the application resumes without issue except that the IMAQ image no longer is updating properly (watching the image control or probing the wire). The memory leak does not return. This makes me suspicious that LabVIEW is not properly disposing of some memory internally with regards to the IMAQ image or control or both. I am posting here in the actor framework community because I am unable to reproduce this memory leak outside of the actor framework.

I have a Camera actor that publishes image information (by value) to subscribers and also provides the ability to directly update the value of an IMAQ image control by being given a reference to that control. This latter point is for ease of use for UI actors not to be overloaded with image messages. This works perfectly except for the memory leak. The image control propery node is written by a Camera actor method that is called at approximately 60Hz. The Camera actor has a single IMAQ image as a class property that is created when the actor is created. This IMAQ image is updated when a camera read happens, and then this IMAQ image (a reference type, see below for documentation) is passed to the IMAQ image control property node. If I simply call the Camera actor read image method inside a while loop and update an image, I do not see this memory leak. I have my Camera actor created such that I can use it as a normal instrument (init, read, close) without actor messaging.

Here's some documentation:

image.PNG

If I simply place a diagram disable structure over this within my actor method, the memory leak disappears.

Any thoughts?

0 Kudos
Message 1 of 11
(5,440 Views)

I'm not really familiar with IMAQ, so just some general thoughts:

On the first glance, this seems to me to me a more IMAQ than an Actor related problem. As a kind of cautious programmer, I tend to close references as I use them . If you distribute the reference to clients, a copy of the reference will be made. So my first guess would be to close the reference after use.

I have seen some strange behaviour with TestStand references which ended up fixed by closing references which by common sense would not have been necessary to close

0 Kudos
Message 2 of 11
(4,510 Views)

Thanks for the response. I think it's possible that it's a combination of a problem between NI-IMAQ and the actor framework, or at least some mechanism that the actor framework uses (like dynamic launching) that isn't clear as to why this occurs.

I don't think it's a reference problem. When I place the diagram disabled structure around this code, the reference is still there. If it was being leaked and the cause of the memory was that, it wouldn't disappear when placing the disabled structure. This reference is passed down to the actor from my top-level actor. This reference doesn't need to be closed since it will be automatically closed out (not leaked) when the top-level actor's actor core closes, which acts as the UI. The original reference was created using the right-click control -> create reference method. These references don't need to be closed, and in fact, calling the close reference primitive on them has no effect.

The IMAQ image wire is a very strange type in LabVIEW. Documentation says that it's a reference and yet it behaves like both at times. I have another bug that I plan on filing to NI. The last link I gave says to treat it as a reference. Yet, I found a case today where if I don't wire an IMAQ image indicator from an IMAQ VI that operates on an IMAQ image, the image is not updated. If I simply wire the indicator to a terminal that goes nowhere, the image is updated (as you would expect even in the unwired case since it is supposedly a reference).

And as I mention under the first link, the behavior described there does not occur from my testing today. It's unclear if this documentation is out of date, simply innaccurate, or if there's bugs happening.

Anyway, this is quite a sticky problem, as I can't reproduce it outside of the actor framework. It's causing my app to generate the memory dialog within a minute or so of use.

0 Kudos
Message 3 of 11
(4,510 Views)

aa82 schrieb:

I don't think it's a reference problem. When I place the diagram disabled structure around this code, the reference is still there. If it was being leaked and the cause of the memory was that, it wouldn't disappear when placing the disabled structure. This reference is passed down to the actor from my top-level actor. This reference doesn't need to be closed since it will be automatically closed out (not leaked) when the top-level actor's actor core closes, which acts as the UI. The original reference was created using the right-click control -> create reference method. These references don't need to be closed, and in fact, calling the close reference primitive on them has no effect.

The IMAQ image wire is a very strange type in LabVIEW. Documentation says that it's a reference and yet it behaves like both at times. I have another bug that I plan on filing to NI. The last link I gave says to treat it as a reference. Yet, I found a case today where if I don't wire an IMAQ image indicator from an IMAQ VI that operates on an IMAQ image, the image is not updated. If I simply wire the indicator to a terminal that goes nowhere, the image is updated (as you would expect even in the unwired case since it is supposedly a reference).

For me, the question is: if you are using the diagram disable, is there really no leak or are you not seeing the leak because when not using it, the object created in the background is tiny enough not ot be seen. So if you write data to the referenence, the memory manager kicks in and allocates memory and makes it visible... just a thought

Relying on the automatic closing of the references leaves you with some uncertainities, about when they are closed.

On the other hand (an almost religious question): why are you publishing the IMAQ control to SubActors instead of sending data from the Actors to the MainActors requesting it to display? In terms of reducing coupling, this would be far better

0 Kudos
Message 4 of 11
(4,510 Views)

I don't want to get off the path here too much, because this memory leak is a showstopper issue for me. But there is no uncertainity when the IMAQ ImageControl (the green, VI server reference) is closed. It is created and closed by the control's owning VI. There is no way to close such a reference. You can explicitly call the close reference primitive on it, and it still will be a valid reference. Try this. There is not a reference leak with that reference. In the screenshot below, the control will go to 1, 5, and then 12, despite having its reference "closed" twice. There is no reference leak whether you explicitly close the reference or not, as verified by the Desktop Execution Trace Toolkit, and it never gets closed anyway until the VI leaves memory.

Reference.PNG

This is getting off on a design tangent, which is often the worry about posting here, though it does explain some detail on the relationship between the UI and Camera actor I describe above. There is zero (or as minimal as you can get) coupling here between my UI actor and Camera actor. The Camera actor simply allows other actors (any actor) to subscribe to the data it publishes. When subscribing to this actor, the subscriber has the option to receive the actual data via messages and also the option of whether to provide a valid control reference to be updated for convenience when the data is published. For a UI actor that is subscribing, such an actor doesn't actually care about EVERY piece of data published and often has zero need to do anything with the data other than display it. So in that case, the UI subscribes to the Camera actor's data by disabling the data messaging and providing a valid control reference. For a Logger actor, that actor subscribes by enabling the data messaging but disabling the control reference updates since it has no need for that. If the UI wanted to do additional processing in addition to displaying, it could enable the data messaging if it wanted. It could even disable the control reference updating if it wanted to explicitly handle what's displayed. It's just that the main use case for the UI actor is to simply display the data. There's no need for the UI actor to be handling all these messages just to display data. If I did that for every actor I needed display from continuously, I'd have tons of messages floating around just to display data. Only the Logger actor needs such data messages since it actually cares about every single piece of data sent out by the Camera actor.

The zero coupling comes from the Camera actor defining an abstract message for the data publishing. The UI and Logger actors provide specific implementations of this class when they subscribe to the Camera actor's data publishing. The Camera actor does nothing but provide this subscription method that says you can receive data or have an image control directly updated or both.

0 Kudos
Message 5 of 11
(4,510 Views)

Hi

Are you creating new IMAQ image for each frame?

And when it is grabbed by camera then you displayed them on GUI?

Do you release that Images after that? When not then it will stay in memory unit it will not crash.

(here is demo code which allocate space for images and after writing to HDD then it will recycle them...)

0 Kudos
Message 6 of 11
(4,510 Views)

No. The IMAQ image is created when the Camera actor is launched and disposed of when the actor stops. Each IMAQ Grab Acquire.vi call updates this one image. When this grab happens in the Camera actor, a message to itself is sent to update all subscribers of the new image. This then sends a message to all subscribers with the image data (converted to an array) and also the image controls.

0 Kudos
Message 7 of 11
(4,510 Views)

Isn't problem that image data (converted to an array) when is it wired to Image indicator is internally converted back to normal IMAQ image reference and this reference is then not disposed by IMAQ dispose vi??

Could you try to Dispose image after it is displayed in Image indicator?

0 Kudos
Message 8 of 11
(4,510 Views)

P.S.: Why you are converting IMAQ image reference to an array data? Why don't you send original image reference?

0 Kudos
Message 9 of 11
(4,510 Views)

JCC_(SK) wrote:

Could you try to Dispose image after it is displayed in Image indicator?

That would kill the image, requiring me to create a new one every time I do an IMAQ Grab Acquire.

JCC_(SK) wrote:

Isn't problem that image data (converted to an array) when is it wired to Image indicator is internally converted back to normal IMAQ image reference and this reference is then not disposed by IMAQ dispose vi??

P.S.: Why you are converting IMAQ image reference to an array data? Why don't you send original image reference?

That's a "To Variant" primitive. Variant is the data type of the ImageControl Value property. I prefer to explicitly cast things for readability. The memory leak happens in either case of implicitly or explicitly casting to variant.

0 Kudos
Message 10 of 11
(4,510 Views)