Callback slow when large object array loaded into function context
Mostrar comentarios más antiguos
I have a strange performance problem when loading an array of handle objects into a function, then subsequently invoking WindowScrollWheelFcn. When scrolling the wheel quickly, the callback interval is very slow, seriously affecting GUI responsiveness. However, if I pass in the object array to the outer function, the callback gets called much more quickly. I'm not sure why.
I tried to whittle the problem down to some test code here, including a handle class, and a function that creates a figure and callback. I could NOT seem to eliminate the need for the Mouse Wheel callback. I tried timers, and calling the function handle directly, but I could not get the problem to occur. So the best way to see it is to run the little test function below, and scroll the mouse wheel on the figure window.
This is just a basically "empty" handle class, and I provided a Static convenience function to create an array of JustHandle objects, which are returned, and also saved to file JH.MAT.
classdef JustHandle < handle
methods (Static)
% Return an array of JustHandle objects, and also save to file.
function JH=MakeArray(NItems)
JH(NItems) = JustHandle(); % pre-allocae object array.
fprintf('Creating array with %d objects...\n', NItems);
for i=1:NItems
JH(i) = JustHandle();
end
fprintf('Saving to file JH.MAT...\n');
save JH JH
end
end
end
And the function that can either take the JH array as an argument, or load it from the JH.MAT file.
function TestSlowCallback(JH)
if nargin < 1
LD = load('JH.mat');
JH = LD.JH;
end
tic;
FIG=figure(200);
FIG.WindowScrollWheelFcn = @ScrollWheelCallback;
function ScrollWheelCallback(src,evt)
fprintf('In callback %.3f\n', toc); % Show time *BETWEEN* callbacks.
tic
end
end
At the command line, create the JustHandle array file, and call the test function:
JH=JustHandle.MakeArray(200000);
TestSlowCallback; % When called w/out arg, file is loaded, and performance is slow.
TestSlowCallback(JH); % When JH is passed in, performace is MUCH better.
With R2018a, when calling w/out arguments, so that load() is called, I get about 300mSec between calls to the ScrollWheel callback. When passing in JH, I get almost an order of magnitude faster, about 40mSec between calls.
Does anyone have an idea why this might be happening, and how to avoid the problem? I understand that function handles have a context that must be passed around, but I'm curious why the difference between loading and passing - isn't the context the same in both cases?
It does seem a bit quirky and obscure, but I wonder if people are getting bitten by it without realizing.
-----
One final note, if I "do something" with the @ScrollWheelCallbackFcn function handle, like return it from the outer TestSlowCallback() function, the problem goes away! So, I guess I have a workaround for the problem, but it just seems really obscure, and I'm not sure why it changes anything.
Thanks for any enlightenment that anyone can provide.
3 comentarios
I did a quick test, though I am not at all an expert in the low level aspects of what goes on in Matlab function calls. Certainly the profiler showed next to no time spent in the ScrollWheelCallback in either case. The time was all 'lost' in the 'Self time (built-ins, overhead, etc.)' category.
I also tried moving the function out to be a local function rather than a nested function and this also seemed generally faster. It's very inconsistent, but as is I was getting a minimum time of 0.013s generally in your slower case, whereas moving to a local function I had some at 0.002s, similar to the version with handles passed in.
The only thing I can see that is different is that in the nested function case you also have LD in the workspace and because it is a nested function it has access to the parent workspace which, in the other case, contains only JH. I certainly couldn't say this is the absolute reason given my relative lack of knowledge of the low-level aspects of how things are coded, but empirically it seems to be the main factor that is different.
Obviously when I switched to a local function this does not have a parent workspace and thus does not contain the structure LD.
Guillaume
el 2 de Abr. de 2019
"The only thing I can see that is different is that in the nested function case you also have LD in the workspace and because it is a nested function it has access to the parent workspace which, in the other case, contains only JH."
Clearing LD inside the if had no effect on performance with my testing, so while I also thought that it may have been the reason, it doesn't appear so.
Dale Roberts
el 2 de Abr. de 2019
Editada: Dale Roberts
el 2 de Abr. de 2019
Respuesta aceptada
Más respuestas (0)
Categorías
Más información sobre Interactive Control and Callbacks en Centro de ayuda y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!