Reputation: 336
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
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
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
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