For example, I have the following class:
classdef testclass < handle
properties
buckets
end
methods
function tc = testclass(sz)
tc.buckets = cell(1, sz);
end
function put(tc,k)
tc.buckets{k}{1} = 1;
end
end
end
And the following example loop, where I compare performance with a plain cell array:
tm = @java.lang.System.currentTimeMillis;
for N=[100 200 400 1000 2000 4000 8000]
tc = testclass(N);
Tstart = tm();
for k=1:N
tc.put(k);
end
Tend = tm();
fprintf(1, 'filling hash class (size %d): %d ms\n', N, Tend - Tstart);
arr = cell(1,N);
Tstart = tm();
for k=1:N
arr{k}{1} = 1;
end
Tend = tm();
fprintf(1, 'filling cell array (size %d): %d ms\n', N, Tend - Tstart);
end
The output is:
filling hash class (size 100): 8 ms
filling cell array (size 100): 0 ms
filling hash class (size 200): 9 ms
filling cell array (size 200): 0 ms
filling hash class (size 400): 24 ms
filling cell array (size 400): 1 ms
filling hash class (size 1000): 108 ms
filling cell array (size 1000): 2 ms
filling hash class (size 2000): 370 ms
filling cell array (size 2000): 5 ms
filling hash class (size 4000): 1396 ms
filling cell array (size 4000): 10 ms
filling hash class (size 8000): 5961 ms
filling cell array (size 8000): 21 ms
As you can see, plain cell array exhibits “linear” performance (which is to be expected), but array wrapped in a class gives horrible quadratic performance.
I tested this on Matlab 2008a and Matlab 2010a.
What causes this? And how can I work around it?
The true power of Matlab is only available to those who know what to avoid 🙂
One major issue with OOP in interpreted languages (Matlab is not alone in this) is the rather spectacular overhead involved with calling methods, as you have noticed. OOP requires completely different design strategies in Matlab, Python, etc. than in C++, Fortran, etc.
Anyway, you had best avoid calling methods so often, and vectorize as much as you can.
Compare this:
where the relevant method in
testclassis modified to handle vectorized as well as looped assignments:Results: