One of the items that came up at the last Online Developer Meeting was basing more of Octave internals on C++ libraries, rather than our own hand-rolled code. This should get us 1) more cross-platform compatibility, 2) less code of our own to maintain with a limited number of volunteers, and 3) better performance as library code has typically been optimized.
Although we haven’t done a root-cause analysis of why Octave has been slowing down over time, it is clear that there is a lot of memory allocations / memory frees going on. My suspicion is that this is because we have relatively heavyweight objects. Creating an
octave_value which holds a
Matrix requires creating and initializing dozens, maybe as many as 50, different member functions and going through multiple inheritance hierarchies.
gsvd.cc, which interacts with LAPACK and Fortran code, I noticed that it was using
Matrix as a way to get temporary, run-time scalable temporary memory. For example, if you need storage for N doubles (where N is known only at run-time) the code might be
Matrix tmp (N, 1); double *ptr = tmp.fortran_vec ();
I can see the appeal. Because we have access to
liboctave, this is a consistent cross-platform way to perform this task. However, it’s also a very expensive in terms of performance.
In the case of
gsvd.cc, I just used the C++ STL and
std::vector<double> tmp (N); double *ptr = tmp.data ();
which should be a better performing alternative.
As yet a third alternative, and possibly the highest performing, there is the
OCTAVE_LOCAL_BUFFER macro which makes use of C++
<memory> library. To do the same thing as above, I can write
OCTAVE_LOCAL_BUFFER(double, ptr, N)
which will create the variable
double *ptr with enough memory for N
I’m making a note of this here, because when interfacing with LAPACK there is often a need for scratchpad memory so the use of
Matrix for temporary memory is likely to be a common pattern that could be replaced all over