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

Class object creation performance

December 11, 2013 8 Comments

Matlab’s Class Object System (MCOS) is a powerful way to develop maintainable, modular, reusable code using a modern Object Oriented Programming (OOP) paradigm. Unfortunately, using OOP in Matlab carries some performance penalties that need to be considered when deciding whether to code in the new paradigm or keep using the older, simpler procedural paradigm. A major resource in this regard is a detailed post from 2012 by Dave Foti, who heads MCOS development at MathWorks.
As Dave pointed out, the importance of MCOS’s overheads only comes into play when our program uses many class objects and calls many short-duration methods. In the majority of cases, this is actually not the case: Our performance bottlenecks are normally I/O, GUI, memory and processing algorithm – not object manipulation and function-call overheads. Unfortunately, Dave’s article left out many ideas for improving MCOS performance in those cases where it does matter.
Today’s article will expand on the sub-topic of MCOS object creation. While it does not directly rely on any undocumented aspect, I have also not seen it directly explained in the official docs. So consider this to be the missing doc page…

Constructor chaining

In his article, Dave’s main suggestion for improving object creation performance was to reduce the number of super-classes. When creating class objects, each creation needs to chain the default values and constructors of its ancestor super-classes. The more superclasses we have, the more modular our code can become, but this makes object creation slightly slower. The effect is typically on the order of a few millisecs or less, so unless we have a very long super-class chain or are bulk-creating numerous objects, this has little impact on the overall program performance.

Object pooling

Objects are typically created at the beginning of a program and used throughout it. In such cases, we only pay the small performance penalty once. In cases where objects are constantly being destroyed and created throughout the program’s duration, consider using object pooling to reuse existing objects. The basic idea is to create a set of ready-to-use objects at the beginning of the program. A static (singleton) dispatcher (factory) object would create this pool of objects in its constructor, possibly with a few new objects ready for use. The factory’s only public interface would be public pull/recycle methods to retrieve and return objects from/to the pool. The program would have no access to the objects pool (except via these public methods), since the pool is stored in the factory object’s private data.
The pull method would create new objects only when asked to retrieve objects from an empty pool; otherwise it would simply return a reference to one of the unused pool objects (which need to be handle class objects to be reference-able). The recycle method will be used to return objects to the pool, once they have been used, to enable these objects to be reused later (via subsequent pulls).
Object pooling entails programming overheads that only make sense when a large number of short-lived objects are constantly being created and destroyed, or when object creation is especially expensive. It is often used in databases (connection pooling), since programs often connect to a database numerous times for short-lived SQL queries. Similar ideas can be found in GUI and I/O programming.
Here is a simple implementation of such a system. The singleton factory class is Widgets and it holds a pool of reusable Widget objects:

% Manage a persistent, global, singleton list of Widget objects
classdef Widgets < handle
    properties (Access=private)
        UnusedWidgets@Widget   % only accept elements of type Widget
    end
    methods (Access=private)
        % Guard the constructor against external invocation.
        % We only want to allow a single instance of this class
        % This is ensured by calling the constructor from the static (non-class) getInstance() function
        function obj = Widgets()
            % Initialize an initial set of Widget objects
            for idx = 1 : 5
                try
                    obj.UnusedWidgets(idx) = Widget;
                catch
                    obj.UnusedWidgets = Widget;  % case of idx==1
                end
            end
        end
    end
    methods (Static)  % Access=public
        % Get a reference to an unused or new widget
        function widget = pull()
            obj = getInstance();
            try
                % Try to return a widget from the list of UnusedWidgets
                widget = obj.UnusedWidgets(end);
                obj.UnusedWidgets(end) = [];  % remove from list
            catch
                widget = Widget;  % create a new Widget object
            end
        end
        % Return a widget to the unused pool, once we are done with it
        function recycle(widget)
            obj = getInstance();
            obj.UnusedWidgets(end+1) = widget;
        end
    end
end
% Concrete singleton implementation
% Note: this is deliberately placed *outside* the class, so that it is not accessible to the user
function obj = getInstance()
    persistent uniqueInstance
    if isempty(uniqueInstance)
        obj = Widgets();
        uniqueInstance = obj;
    else
        obj = uniqueInstance;
    end
end

% Manage a persistent, global, singleton list of Widget objects classdef Widgets < handle properties (Access=private) UnusedWidgets@Widget % only accept elements of type Widget end methods (Access=private) % Guard the constructor against external invocation. % We only want to allow a single instance of this class % This is ensured by calling the constructor from the static (non-class) getInstance() function function obj = Widgets() % Initialize an initial set of Widget objects for idx = 1 : 5 try obj.UnusedWidgets(idx) = Widget; catch obj.UnusedWidgets = Widget; % case of idx==1 end end end end methods (Static) % Access=public % Get a reference to an unused or new widget function widget = pull() obj = getInstance(); try % Try to return a widget from the list of UnusedWidgets widget = obj.UnusedWidgets(end); obj.UnusedWidgets(end) = []; % remove from list catch widget = Widget; % create a new Widget object end end % Return a widget to the unused pool, once we are done with it function recycle(widget) obj = getInstance(); obj.UnusedWidgets(end+1) = widget; end end end % Concrete singleton implementation % Note: this is deliberately placed *outside* the class, so that it is not accessible to the user function obj = getInstance() persistent uniqueInstance if isempty(uniqueInstance) obj = Widgets(); uniqueInstance = obj; else obj = uniqueInstance; end end

We can access and use the Widgets object pool as follows:

% Retrieve a Widget object instance from the pool of objects, or create a new instance as needed
widget = Widgets.pull();
% Now use this widget object until we're done with it
% Return the object to the pool, for possible later reuse
Widgets.recycle(widget);

% Retrieve a Widget object instance from the pool of objects, or create a new instance as needed widget = Widgets.pull(); % Now use this widget object until we're done with it % Return the object to the pool, for possible later reuse Widgets.recycle(widget);

Credit: inspired by Bobby Nedelkovski’s Singleton class implementation

Handle vs. value class objects

Another consideration when designing classes is that while handle classes are slightly slower to create (due to multiple super-class overheads), they are typically much faster to use. The reason is that handle classes are passed to functions by reference, whereas value classes are passes by value. Whenever we modify a handle class property within a function, we directly manipulate the relevant property memory. On the other hand, when we manipulate a value class property, a copy of the class needs to be created and then the modified class needs to be copied back to the original object’s memory (using Matlab’s Copy-on-Write mechanism). Since we cannot normally anticipate all usage patterns of a class when we create it, I suggest to create any new user class as handle class, unless there is a specific good reason to make it a value class. All it takes is to add the handle (or hgsetget) inheritance to the class definition:

classdef MyClass < handle

classdef MyClass < handle

Preallocation

When implicit expansion of class-object arrays takes place, an abbreviated version of object instance creation takes place, which bypasses the constructor calls and just copies the instance properties. For example, array(9)=Widget creates an array of 9 separate Widget objects, but the Widget constructor is only called for array(1) and array(9); array(1) is then expanded (copied-over) to the remaining objects array(2:8).
When preallocating, ensure that you are using the maximal expected array size. There is no point in preallocating an empty array or an array having a smaller size than the expected maximum, since dynamic memory reallocation will automatically kick-in within the processing-loop. For this reason, avoid using the empty() method of class objects to preallocate – use repmat instead (ref).
When using repmat to replicate class objects, always be careful to note whether you are replicating the object itself (this happens if your class does NOT derive from handle) or its reference handle (which happens if you derive the class from handle). If you are replicating objects, then you can safely edit any of their properties independently of each other; but if you replicate references, you are merely using multiple copies of the same reference, so that modifying referenced object #1 will also automatically affect all the other referenced objects. This may or may not be suitable for your particular program requirements, so be careful to check carefully. If you actually need to use independent object copies, you will need to call the class constructor multiple times, once for each new independent object (ref).
Preallocation of class objects (class instances) can be used not just as a means of avoiding dynamic allocation, but also as a means of controlling the time of object initialization. Object initialization, typically done in the class’s constructor method, could be lengthy (depending on your specific application). By preallocating the object, we can control the exact timing in which this initialization occurs, possibly at such a time that is less time-critical in the regular application time-flow. This relates to the concepts of lazy initialization, a special case of deferred (or demand-driven) evaluation.
For additional aspects of preallocation performance, refer to my article from last year, which discusses class objects only briefly, but expands on the other data types.

London training course – March 2014

If you are interested in improving your Matlab application’s performance and your Matlab programming skills in general, join my upcoming Advanced Matlab Programming course in London, March 2014 – an intensive 2 day course on best practices, preparing professional reports and performance tuning. I guarantee that following this course your Matlab programming skills will be at a higher level.

Related posts:

  1. Handle object as default class property value – MCOS property initialization has a documented but unexpected behavior that could cause many bugs in user code. ...
  2. Class object tab completion & improper field names – Tab completions and property access can be customized for user-created Matlab classes. ...
  3. Creating a simple UDD class – This article explains how to create and test custom UDD packages, classes and objects...
  4. General-use object copy – Matlab's dual internal serialization/deserialization functions can be used to create duplicates of any object. ...
  5. Performance: accessing handle properties – Handle object property access (get/set) performance can be significantly improved using dot-notation. ...
  6. Accessing private object properties – Private properties of Matlab class objects can be accessed (read and write) using some undocumented techniques. ...
MCOS Performance Pure Matlab
Print Print
« Previous
Next »
8 Responses
  1. Andrew December 11, 2013 at 11:39 Reply

    Interesting use of The MathWorks calls “class-related” functions. Is there a reason that you didn’t make getInstance() an (Access=private,Static,Hidden) method instead? Also, is there a reason for not making Widgets a (Sealed) class to prevent subclassing?

    • Yair Altman December 11, 2013 at 12:09 Reply

      @Andrew – I could indeed make getInstance() Static+private (no need to make it hidden), but then I’d need to call it via the Widgets. prefix in pull()/recycle():

      obj = Widgets.getInstance();

      obj = Widgets.getInstance();

      There’s also the small matter of performance – I believe that calling a sub-function as in my implementation is slightly faster than a class method invocation.

      Not major reasons, I admit. There’s a lot of personal taste that goes into such implementations, and there are of course other good implementations. I’ve lost count of the number of singleton implementations I’ve seen over the years. It’s one of those classes that every newbie gets to program as an exercise, and doesn’t know that he got it wrong until he’s shown his/her errors in a technical job interview. Hopefully, my implementation doesn’t fall into this latter category…

      As for not making Widgets Sealed, I see no reason to prevent sub-classes from reimplementing the pool differently. For example, instead of retrieving the last-recycled object, retrieving the oldest one in the pool.

  2. MatMan December 12, 2013 at 03:27 Reply

    You could have mentioned that since Matlab 2011a (I think) you can copy handle classes without invoking the constructor: http://www.mathworks.com/help/matlab/ref/matlab.mixin.copyableclass.html

    Instead of a pool of objects I store only one object and create as many copies as I need when I need them. I haven’t analyzed if a factory approach would be faster though…

    • Yair Altman December 12, 2013 at 05:43 Reply

      Thanks for mentioning this, matlab.mixin.Copyable can indeed be useful for fast shallow copies, in cases that do not require deep copies. And yes, it was indeed added in R2011a.

      Readers interested in object copying might find the following discussion interesting: https://www.mathworks.com/matlabcentral/newsreader/view_thread/257925

    • MatMan December 12, 2013 at 07:24 Reply

      A small addition:
      matlab.mixin.Copyable can also be used for deep copies by overloading the copyElement method as described in the documentation.
      Thanks for clearing up that when it was added!

  3. Matt Whitaker December 12, 2013 at 12:22 Reply

    Hi Yair,
    A note on the preallocation. If you have a parameter passed in on your class the automatically expanding classes will be called with a parameter constructor

    So if your Widgets class had a varargin input for example then when you try

    array(9)=Widgets('param');

    array(9)=Widgets('param');

    will call the constructor passing ‘param’ in varargin{1} for the first constructor but then passes in an empty varargin for the next
    So the moral I think is to have a no-parameter constructor defined if you are going to use this.

    At least that’s the way it seems to work on my R2012b
    Cheers

    Matt

    • Yair Altman December 12, 2013 at 12:24 Reply

      @Matt – thanks for the clarification

  4. Accessing private object properties | Undocumented Matlab December 18, 2013 at 11:16 Reply

    […] a copy of the original. Even if our original object is a handle class, the struct would still be a shallow copy and not a real reference to the object data.Mex’s standard mxGetProperty cannot be used on […]

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