Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Performance: accessing handle properties

November 20, 2013 13 Comments

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.

% 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.

% 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.

% 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);

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.

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

% 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.

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.

% 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!

Related posts:

  1. Accessing private object properties – Private properties of Matlab class objects can be accessed (read and write) using some undocumented techniques. ...
  2. Displaying hidden handle properties – I present two ways of checking undocumented hidden properties in Matlab Handle Graphics (HG) handles...
  3. Adding custom properties to GUI objects – It is very easy to add custom user-defined properties and methods to GUI handles and Java references in Matlab. ...
  4. Handle Graphics Behavior – HG behaviors are an important aspect of Matlab graphics that enable custom control of handle functionality. ...
  5. Adding dynamic properties to graphic handles – It is easy and very useful to attach dynamic properties to Matlab graphics objects in run-time. ...
  6. Plot LimInclude properties – The plot objects' XLimInclude, YLimInclude, ZLimInclude, ALimInclude and CLimInclude properties are an important feature, that has both functional and performance implications....
Handle graphics HG2 MCOS Performance Pure Matlab Undocumented feature Undocumented function
Print Print
« Previous
Next »
13 Responses
  1. oro77 November 20, 2013 at 18:50 Reply

    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 ?

    jb = javax.swing.JButton;

    jb = javax.swing.JButton;

    • Yair Altman November 21, 2013 at 02:12 Reply

      @oro77 – http://undocumentedmatlab.com/blog/javacomponent/

  2. Lucius Domitius Ahenobarbus November 21, 2013 at 01:05 Reply

    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.

  3. Dan November 21, 2013 at 11:33 Reply

    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:

    function SpeedTests
       fig = figure;
       for i = 1:4
          hObj(i) = subplot(2,2,i);
          handleObj{i} = handle(hObj(i));
          handleObjs2(i) = handle(hObj(i));
       end
       for itest = 1:1000
          subfun(handleObj,hObj,handleObjs2);
       end
       return
    end
     
    function subfun(handleObj,hObj,handleObjs2)
       for i = 1:4
          pos0 = handleObjs2(i).Position;
          pos1 = handleObj{i}.Position;
          pos2 = get(hObj(i),'Position');
          pos3 = handleObj{i}.Position;
          XLIMS = handleObj{i}.XLim;
       end
    end

    function SpeedTests fig = figure; for i = 1:4 hObj(i) = subplot(2,2,i); handleObj{i} = handle(hObj(i)); handleObjs2(i) = handle(hObj(i)); end for itest = 1:1000 subfun(handleObj,hObj,handleObjs2); end return end function subfun(handleObj,hObj,handleObjs2) for i = 1:4 pos0 = handleObjs2(i).Position; pos1 = handleObj{i}.Position; pos2 = get(hObj(i),'Position'); pos3 = handleObj{i}.Position; XLIMS = handleObj{i}.XLim; end end

    Any thoughts?

  4. Malcolm Lidierth November 21, 2013 at 19:16 Reply

    While this may not be a real application test case note that using GShell (which uses a Groovy shell) from Waterloo in MATLAB gives:

    tic;
    GShell.setVariable('button', jhb);
    GShell.eval('for (def idx=0; idx < 10000; idx++) { button.setText("testing")'); 
    toc;

    tic; GShell.setVariable('button', jhb); GShell.eval('for (def idx=0; idx < 10000; idx++) { button.setText("testing")'); toc;

    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.

    • Malcolm Lidierth November 22, 2013 at 05:40 Reply

      PPS. Adding the code to a script file and using run allows the compiled code to be used each time. Then we see

      >> GShell.load('/Users/ML/blogtest.groovy')  % Load and compile once
      ans =
           1
       
      >> tic;GShell.run();toc
      Elapsed time is 0.060009 seconds.
      >> tic;GShell.run();toc
      Elapsed time is 0.019712 seconds.
      >> tic;GShell.run();toc
      Elapsed time is 0.003378 seconds.
      >> tic;GShell.run();toc
      Elapsed time is 0.003129 seconds.
      >> tic;GShell.run();toc
      Elapsed time is 0.003126 seconds.
      >> tic;GShell.run();toc
      Elapsed time is 0.003531 seconds.
      >> tic;GShell.run();toc
      Elapsed time is 0.003365 seconds.
      >> tic;GShell.run();toc
      Elapsed time is 0.003394 seconds.

      >> GShell.load('/Users/ML/blogtest.groovy') % Load and compile once ans = 1 >> tic;GShell.run();toc Elapsed time is 0.060009 seconds. >> tic;GShell.run();toc Elapsed time is 0.019712 seconds. >> tic;GShell.run();toc Elapsed time is 0.003378 seconds. >> tic;GShell.run();toc Elapsed time is 0.003129 seconds. >> tic;GShell.run();toc Elapsed time is 0.003126 seconds. >> tic;GShell.run();toc Elapsed time is 0.003531 seconds. >> tic;GShell.run();toc Elapsed time is 0.003365 seconds. >> tic;GShell.run();toc Elapsed time is 0.003394 seconds.

      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 with GShell.runQuery which uses GShell.runEDT if it can, and GShell.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.

  5. Xiaohu November 22, 2013 at 16:18 Reply

    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?

    • Yair Altman November 23, 2013 at 08:45 Reply

      @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.

    • Andrew November 26, 2013 at 14:47 Reply

      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.

    • Yair Altman November 26, 2013 at 15:03 Reply

      @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.

  6. Bjorn November 26, 2013 at 06:10 Reply

    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.

    %Setup many axes in one figure
    tmp = figure;
    Fig = zeros(1,10000);
    for idx=1:10000
        Fig(idx) = axes('parent',tmp);
    end
     
    % Using standard set() function
    tic, for idx=1:10000, set(Fig(idx),'tag','testing'); end, toc % Elapsed time is 0.163880 seconds
     
    % Using the HG handle() wrapper within the loop
    tic, for idx=1:10000, hFig = handle(Fig(idx)); set(hFig,'tag','testing'); end, toc % Elapsed time is 0.375456 seconds
     
    % Using the HG handle() wrapper outside of the loop
    tic
    hFig = handle(Fig);
    for idx=1:10000, set(hFig(idx),'tag','testing'); end, 
    toc % Elapsed time is 0.241068 seconds
     
    % Using dot notation with handle() wrapper within the loop
    tic
    for idx=1:10000, hFig = handle(Fig(idx)); hFig.tag = 'testing'; end
    toc % Elapsed time is 0.290306 seconds
     
    % Using dot notation with handle() wrapper outside of the loop
    tic
    hFig = handle(Fig);
    for idx=1:10000, hFig(idx).tag = 'testing'; end
    toc % Elapsed time is 3.585026 seconds

    %Setup many axes in one figure tmp = figure; Fig = zeros(1,10000); for idx=1:10000 Fig(idx) = axes('parent',tmp); end % Using standard set() function tic, for idx=1:10000, set(Fig(idx),'tag','testing'); end, toc % Elapsed time is 0.163880 seconds % Using the HG handle() wrapper within the loop tic, for idx=1:10000, hFig = handle(Fig(idx)); set(hFig,'tag','testing'); end, toc % Elapsed time is 0.375456 seconds % Using the HG handle() wrapper outside of the loop tic hFig = handle(Fig); for idx=1:10000, set(hFig(idx),'tag','testing'); end, toc % Elapsed time is 0.241068 seconds % Using dot notation with handle() wrapper within the loop tic for idx=1:10000, hFig = handle(Fig(idx)); hFig.tag = 'testing'; end toc % Elapsed time is 0.290306 seconds % Using dot notation with handle() wrapper outside of the loop tic hFig = handle(Fig); for idx=1:10000, hFig(idx).tag = 'testing'; end toc % Elapsed time is 3.585026 seconds

    • Andrew November 26, 2013 at 14:21 Reply

      Interesting

    • Andrew November 26, 2013 at 14:29 Reply

      … 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.

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top