05-16-2017 04:05 PM
I have been given a dll with a single function, that is being called by a Call Library Function node (CLFN). Each time the CLFN is run, its execution time increases. This is with the same inputs provided and the same outputs generated. Execution starts at around 0.8 secs and linearly increases to 3 seconds, over 100 calls. It gets slower as the number of calls increase. I do not observe any significant memory changes over these calls. Exiting LabVIEW is needed to return back to a 0.8 second execution.
I've been working with the developer of the dll and have been told there is no such delay if the dll is called multiple times from within LabWindows/CVI environment.
I'll describe the calculation the dll below, but I can't understand what is going on here. I've used many dlls with the CLFN in the past and never experienced this type of behavior. How is it possible LabVIEW has this happen with the CLFN, but the LabWindows/CVI code does not?
The dll is a complicated trajectory generator, which has many inputs and really just outputs a double 1D array. This output array is preallocated by LabVIEW and typically is sized at 1,080,000 elements. The dll typically only populates values into a third of this array, and leaves the extra elements at zeroes. That is it returns all 1,080,000 elements each time.
Solved! Go to Solution.
05-17-2017 10:18 AM
Which thread setting are you using for the CLF? I would recommend running "in any thread" in order to avoid execution slowdown.
05-17-2017 11:31 AM
The "run in any thread" option is being used and I have tried unloading the dll as explained here (http://digital.ni.com/public.nsf/allkb/77594203D78D12278625729100758BE5), without any change in behavior.
05-17-2017 01:28 PM
@cbl-amo wrote:
I have been given a dll with a single function, that is being called by a Call Library Function node (CLFN). Each time the CLFN is run, its execution time increases. This is with the same inputs provided and the same outputs generated. Execution starts at around 0.8 secs and linearly increases to 3 seconds, over 100 calls. It gets slower as the number of calls increase. I do not observe any significant memory changes over these calls. Exiting LabVIEW is needed to return back to a 0.8 second execution.
I've been working with the developer of the dll and have been told there is no such delay if the dll is called multiple times from within LabWindows/CVI environment.
I'll describe the calculation the dll below, but I can't understand what is going on here. I've used many dlls with the CLFN in the past and never experienced this type of behavior. How is it possible LabVIEW has this happen with the CLFN, but the LabWindows/CVI code does not?
The dll is a complicated trajectory generator, which has many inputs and really just outputs a double 1D array. This output array is preallocated by LabVIEW and typically is sized at 1,080,000 elements. The dll typically only populates values into a third of this array, and leaves the extra elements at zeroes. That is it returns all 1,080,000 elements each time.
If that is indeed true, I would suspect the delay is elsewhere. can you show us the code including where you are getting those performance numbers?
Ben
05-17-2017 01:28 PM
Can you share your code, as well as an example of how the LabWindows code calls the same DLL? A 1-million-element array is fairly large, and if you're allocating a new array each time but the LabWindows code reuses the existing one, that might explain some of it. In particular, if for some reason you're building an increasingly large array on each call to the DLL, you could see behavior like this.
05-17-2017 01:40 PM
@nathand wrote:
Can you share your code, as well as an example of how the LabWindows code calls the same DLL? A 1-million-element array is fairly large, and if you're allocating a new array each time but the LabWindows code reuses the existing one, that might explain some of it. In particular, if for some reason you're building an increasingly large array on each call to the DLL, you could see behavior like this.
Excellent point.
Wrapping the dll in an Action Engine that passes in a fixed size array stored in a shift register would be a way to eliminate repeatedly allocating memory... I think.
Actions:
Init - init an array of the right size and shove it a SR.
Invoke - Calls the dll and passes in the array from the SR.
The non-growth of memory may be due to LV seeing the buffer is no longer used and returns the buffer to its inter pool of memory but the slow down may be from memory fragmentation requiring more time to find a contiguous block for the array.
I like that thought Nathan!
Ben
05-17-2017 03:27 PM
I really appreciate the input and thoughts on this situation. Unfortunately, I can't share any code, but I can share some screen captures that I hope address the suggestions. I created a simple VI for a timing study once the issue was discovered and it operates the way the dll is used in a bigger application. The graph shows the increasing execution time.
In order to quickly see if re-using the same array has any impact, I moved the array initialization outside the for loop. As the image shows, there was no change in the execution.
05-17-2017 03:42 PM
Moving the Initialize Array hasn't changed anything because you're still requiring LabVIEW to copy the entire initialized array for each iteration of the for loop: that is, you've gone from allocating a clean array on each iteration, to copying the already-allocated clean array (because LabVIEW has to hold onto the unmodified allocated array for the next iteration).
What happens if you replace the array tunnels with shift registers? That should allow LabVIEW to reuse the same array on each call, although it also potentially changes the behavior of the application since on every call after the first, you're passing an array that's already been filled in once. That's where it would be helpful to know more about what is going on inside the DLL call, and how you're calling the DLL from LabWindows.
05-17-2017 04:05 PM
Ha, I was thinking about using shift registers instead and had just finished testing when I saw your reply. It doesn't appear to change the behavior though.
05-17-2017 04:06 PM
It looks like this behavior may be related to the cvirte.dll (CVI Run-time dll) functions used by our custom dll.
I was disappointed (and surprised) that unloading the custom dll did not reset the execution time. But by using the process explorer from the sysinternals toolbox, I noticed that the cvirte.dll came into memory along with the custom dll, but was not unloaded when the custom dll was unloaded.
We then created a executable in LabWindows/CVI which used the same dll, cvirte.dll, and now see the increasing times with that executable. The previous test I mentioned was done in the LabWindows/CVI development environment, which did not use cvirte.dll.
I've been told the custom dll can be easily changed to not use the CVI functions, so that work is being done now.
I'll mark this entry as the solution for now and if any extra information comes up, I'll add it at that time.