Jacob
Jacob

Reputation: 336

How to avoid Matlab taking exponential time when creating a handle object array as an object property

It seems to me that when creating an array of simple handle objects in Matlab time scales about linear. However, if I create exactly the same array and store it as a property of an object, time scales exponentially - so the program gets very slow when many objects are created.

My question is why this is happening and how it can be avoided? Is the pre-allocation for object properties not properly implemented in my code or is there a fundamental problem with the way Matlab handles these things?

I wrote a simple test to illustrate the issue:

Code of simple Object:

classdef SomeSimpleObject < handle
% SomeSimpleObject defines an Object that has one property

properties
    property=0;
end

methods
    function SimpleObj=SomeSimpleObject()
        if nargin~=0
            SimpleObj.property=1;
        end
    end
end

end

Using the following Script to create a 1x10.000 array of these simple objects takes according to the profiler 0,4 sec on my machine:

for n=10000:-1:1 % counting backwards for Memory pre-allocation
    ObjectList(n)=SomeSimpleObject();
end

However doing the same thing inside a class constructor and storing the array of 10.000 objects as a property takes 59 sec and it gets much worse quickly. Try it by creating an object from this class (e.g. a=HostingObject)

classdef HostingObject < handle
% This Objects Hosts a List of Objects that are created in the
% constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=HostingObject()    
        for n=10000:-1:1 % counting backwards for Memory pre-allocation
            obj.ObjectList(n)=SomeSimpleObject();
        end
    end
end

end

Searching for an Answer I came across a discussion on Matlab memory allocation and garbage collection. The Answer of Mikhail (also not directly related to my question) made me think that it might be a fundamental problem with the way Matlab implements objects, but I'm still not sure.

Upvotes: 9

Views: 3439

Answers (3)

Jacob
Jacob

Reputation: 336

Inspired by the answers of @Jonas Heidelberg and @Tobias Heß I came up with the following solution that does not need cell arrays at all. The objects are stored in an auxiliary array and once this is completed they are copied to the property array:

Code for HostingObject with array "post-allocation":

classdef JacobHostingObject < handle
% This Objects Hosts a List of Objects that are created in the constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=JacobHostingObject()         
        for n=10000:-1:1 % counting backwards for Memory pre-allocation         
            a(n)=SomeSimpleObject(); % auxiliary array for "post-allocation"           
        end            
         obj.ObjectList=a; % "post-allocation"
    end
end

end

So how do the three solutions (Jonas, Tobias and mine) perform?

I ran some tests (with MATLAB R2011b 64bit) to compare them:

10.000 Objects

Elapsed Time: Tobias:0,30 sec; Jacob:0,31 sec; Jonas:2,02 sec; Original:56,79 sec

100.000 Objects

Elapsed Time: Tobias:2,42 sec; Jacob:2,95 sec; Jonas:203,03 sec

1.000.000 Objects

Elapsed Time: Tobias:23,84 sec; Jacob:29,18 sec

So it looks like Tobias version is the fastest solution

It is interesting to note, that Jonas solution is much better than the original but scales much worse to the other two solutions. This confirms the observation that I made in my earlier question "slow performance when storing handle objects in a cell array". It is a bit ironic that using the technique that was cause of my earlier problem turns out to be an improvement to this problem. Yet, Tobias solution even answers my old question as well (I will post a reference there).

However, it is still not clear what is actually going on inside MATLAB that causes the differences in performance. It might be helpful to get an understanding of this to avoid running into similar problems in the future!

Upvotes: 4

Tobias He&#223;
Tobias He&#223;

Reputation: 268

I found an onther answer. I think using a cell array is not a good solution because you have not the same accsses to the objects as in an array. But you can use a cell as workaround for the problem:

classdef HostingObject < handle
% This Objects Hosts a List of Objects that are created in the
% constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=HostingObject()

        % Creating first a cell array
        helpCell = cell(10000,1);
        for n=1:10000 
            helpCell{n}=SomeSimpleObject();
        end

        % Convert the cell array to the object array
        obj.ObjectList = horzcat(helpCell{:});

    end

end

end

Upvotes: 2

Jonas Heidelberg
Jonas Heidelberg

Reputation: 5024

I don't know why your code is slow, but I found a way to fix it: use a cell array instead of a normal array. I don't find it completely intuitive myself, but here are my profiling results:

>> tic,a=HostingObject;toc
Elapsed time is 105.320128 seconds.

>> tic,a=JonasHostingObject;toc
Elapsed time is 2.394570 seconds.

The object is defined as follows:

classdef JonasHostingObject < handle
properties
    ObjectList
end
methods
    function obj=JonasHostingObject()    
        obj.ObjectList=cell(10000,1);
        for n=1:10000
            obj.ObjectList{n}=SomeSimpleObject();
        end
    end
end    
end

I'm using MATLAB R2011a 64bit, in case it matters.

Upvotes: 4

Related Questions