Graphic handle properties
There are several ways to access (read or update) Handle Graphics object properties. The simplest (and documented) way is to use the built-in get and set functions on the HG object’s handle. However, it is not the fastest: a significant speedup is possible (see below).
Accessing individual properties is so fast that this speedup may not seem important. Individual properties are accessed in tens or hundreds of microseconds, which is a very short time for most Matlab programs. Indeed, if our application seldom accesses properties, it is probably not worth the effort to optimize this particular aspect of the program:
% Individual property access is extremely fast: hFig = figure; tic, figName = get(hFig,'name'); toc % Elapsed time is 0.000229 seconds. tic, set(hFig,'name','testing'); toc % Elapsed time is 0.000270 seconds. |
But if we have thousands of reads and/or updates, this could possibly become an important factor (drawnow calls are intentionally omitted to illustrate the effect):
% Using the standard set() function tic, for idx=1:10000, set(hFig,'name','testing'); end, toc % Elapsed time is 0.229772 seconds. % Using the HG handle() wrapper is about 25% faster (or 1.3x speedup): tic hFig = handle(hFig); for idx=1:10000, set(hFig,'name','testing'); end toc % Elapsed time is 0.170205 seconds. % Using the HG handle() wrapper with dot notation is even faster (65% faster, or 2.7x speedup): tic hFig = handle(hFig); for idx=1:10000, hFig.name='testing'; end toc % Elapsed time is 0.083762 seconds. |
Similar results occur when trying to get() a property value:
% Using the standard set() function tic, for idx=1:10000, s=get(hFig,'name'); end, toc % Elapsed time is 0.140865 seconds. % Using the HG handle() wrapper is about 25% faster (or 1.3x speedup): tic, hFig=handle(hFig); for idx=1:10000, s=get(hFig,'name'); end, toc % Elapsed time is 0.108543 seconds. % Using the HG handle() wrapper with dot notation is even faster (62% faster, or 2.6x speedup): tic, hFig=handle(hFig); for idx=1:10000, s=hFig.name; end, toc % Elapsed time is 0.053423 seconds. |
We learn from this that using the HG handle() wrapper function is useful for improving performance. This has the benefit of improving our code performance with minimal changes to our code, by simply updating our handle to be a handle() wrapper:
hFig = handle(hFig); |
Using the handle’d handle enables further performance benefits if we use the dot notation (handle.propertyName
), rather than use the familiar get/set functions.
Note that both the handle function and its beneficial effects on performance are undocumented.
Java reference properties
The same conclusions also hold true for Java objects, where it turns out that using handle() and the simple dot notation is 2-6 times as fast as using the Java set<PropName> and get<PropName> functions, due to Matlab-Java interface aspects:
jb = javax.swing.JButton; % Using the standard set() function tic, for idx=1:10000, set(jb,'Text','testing'); end, toc % Elapsed time is 0.278516 seconds. % Using the HG handle() wrapper is about 35% faster (or 1.6x speedup): jhb = handle(jb); tic, for idx=1:10000, set(jhb,'Text','testing'); end, toc % Elapsed time is 0.175018 seconds. % Using the HG handle() wrapper with dot notation is even faster (65% faster, or 2.8x speedup): tic, for idx=1:10000, jhb.text='testing'; end, toc % Elapsed time is 0.100239 seconds. % Using the Java setText() function, is actually slower (faster with the handle() wrapper, but still slower than dot-notation): tic, for idx=1:10000, jb.setText('testing'); end, toc % Elapsed time is 0.587543 seconds. tic, for idx=1:10000, jhb.setText('testing'); end, toc % Elapsed time is 0.201635 seconds. |
The same holds true also for retrieving property values via the get function.
User handle class properties
Exactly the same conclusions also apply to non-graphical user classes that derive from the base handle class regarding property access. In this case, we derive the hgsetget built-in class, which provides a handle class with the standard get/set functions. Note that this is documented – it is only the performance implications that are undocumented in this case.
We first create a simple class for testing:
% Define a simple handle class classdef TestClass < hgsetget properties name end end |
Now let’s test both sides of the property access (get/set) – first let’s set the property value:
obj = TestClass; % Using the standard set() function tic, for idx=1:10000, set(obj,'name','testing'); end, toc % Elapsed time is 0.138276 seconds. % Using class.propName notation - 72x faster! tic, for idx=1:10000, obj.name='testing'; end, toc % Elapsed time is 0.001906 seconds. |
And similarly for retrieving a property value:
% Using the standard set() function tic, for idx=1:10000, a=get(obj,'name'); end, toc % Elapsed time is 0.105168 seconds. % Using class.propName notation - 6.5x faster tic, for idx=1:10000, a=obj.name; end, toc % Elapsed time is 0.016179 seconds. |
Conclusions
The general conclusion is that we should always strive to use the dot notation (handle.propertyName
), rather than use the familiar get/set functions, in performance hotspots. Naturally, doing this in non-hotspot locations is futile, since accessing individual properties is relatively fast.
In the upcoming HG2, when all of Matlab’s GUI and graphic objects will use Matlab classes, this conclusion will be more important than ever. Initial tests on the HG2 alpha (that anyone can access) show that they hold true for HG2 just as they do in the current HG1.
The handle() function wrapper produces a UDD (schema) object, so while I have not specifically tested non-HG schema objects, I would be very surprised if the conclusions do not hold true for all UDD objects in general.
I have also not [yet] tested other types of handles (ActiveX/COM, Dot-Net etc.) but again, I would be very surprised if the conclusions would be any different.
If this performance tip has piqued your interest, then you might be interested in the several hundred other tips in my upcoming book “MATLAB Performance Tuning” (CRC Press, 2014). I’ll post a note on this blog letting everyone know when it’s officially available. In the meantime, enjoy my other performance-related articles – there are already several dozen of them by now, and the list will continue to grow…
Editorial note: In the past month I’ve gone to quite a lot of effort to improve the performance of this website. Most users should now see pages loading about twice as fast as one month ago. The effect should be especially noticeable on mobile devices connected over mobile, which is much slower than wifi/cable. I still have a few additional tweak ideas, so I expect performance to slightly improve even further in the upcoming weeks. Enjoy reading!
Thank you very much, I did not know about the handle() tip. It will increase the performance of my GUI.
I have a question concerning the java Button. How do you put it in the figure ? There is no parent member in the handle. How to change the size of the button using the java button ?
@oro77 – http://undocumentedmatlab.com/blog/javacomponent/
Thanks a lot! there is another thing, which makes this even more interesting for me: With the dot-notation, one can use the autocomplete-functionality 🙂 what makes coding a bit faster for me in many cases.
Yair, I noticed something interesting. It appears that you pay the time penalty the first time you access any property within a given scope. Try this: create a handle object and pass it into a function (you can pass it in within a cell array, at a minimum). The first time you access any property within the function you pay the time penalty, but all subsequent calls are fast. BUT: you pay that penalty every time you call the function… Try profiling this:
Any thoughts?
While this may not be a real application test case note that using GShell (which uses a Groovy shell) from Waterloo in MATLAB gives:
Elapsed time is 0.019272 seconds.
A ~10x improvement on the best of the above on my machine (after GShell warm up).
Further info at http://waterloo.sourceforge.net/groovy/GShell.html
Horses-for-courses: expect JVM languages to outperform MATLAB on JVM operations ; and MATLAB to (substantially) outperform the JVM when working with natives.
PPS. Adding the code to a script file and using run allows the compiled code to be used each time. Then we see
The performance improvements are down to HotSpot I guess.
As this is a JButton, the code should really be run on the EDT.
Using
GShell.runEDT
– which uses invokeAndWait – performance returns to ~0.03s.Using
GShell.runLater
– which uses invokeLater – performance improves another 10x (the MATLAB thread is not blocked as control returns as soon as the code is posted to the EDT).invokeAndWait cannot be called if already on the EDT (e.g. if javaObjectEDT has been used on the button).
GShell
solves that withGShell.runQuery
which usesGShell.runEDT
if it can, andGShell.runLater
otherwise.Note that GShell is independent of the rest of the Waterloo code – in fact it’s wrapped in an RStudio project folder and can be used from MATLAB, R, Python, SciLab, JRuby etc. It can be used to run any Java/Groovy code and control threading e.g. to create a background SwingWorker thread or work on the JavaFX platform thread.
GShell contains little or no novel code – it’s just giving easy access to a Groovy shell instance from other scripting environments.
Nice tip (as always)!
It is however surprising to me that using dot notation is actually faster. As you probably know, method invocation using function notation is typically faster in Matlab, see:
http://blogs.mathworks.com/loren/2012/03/26/considering-performance-in-object-oriented-matlab-code/#11
http://stackoverflow.com/questions/1693429/is-matlab-oop-slow-or-am-i-doing-something-wrong
Any insight on this?
@Xiaohu – I do not understand why this is, but it appears to be consistent. If anyone has an explanation, I’d be happy to learn.
This is not really the case of two different ways of invoking a method. We’re setting or getting a property. Properties can either be directly specified/obtained using set/get methods (allowing for things like validation) or via “dot” notation. The latter is much simpler and probably why this is faster. Indeed, trying to get nonexistent properties using the various methods shows that they return different error messages. When setting nonexistent properties, the set method returns an error, but the “dot” notation methods obviously do not. This additional overhead of validation may be what is slowing down get/set over repeated calls.
@Andrew – you may indeed be correct, but when we use a.B=c notation, the setB(a,c) function is still getting invoked if you declare it, which seems to indicate that the opposite is the case. But then it would not explain why a.B would be faster than calling setB() directly. I don’t have a good answer to explain the apparent contradiction.
This seems to be a good approach when resetting the same handle over and over again. Not quite the case when updating many different graphical objects.
Interesting
… the blog apparently ate my n-dash and the rest of my post. In any case, similarly, I wonder which method would be fastest for getting/setting multiple properties of the same handle when using cell arrays, i.e., as in this StackOverflow/Matlab answer of mine.