Jarrett Billingsley wrote:
On Mon, Feb 2, 2009 at 8:31 AM, Lars Kyllingstad
<pub...@kyllingen.nospamnet> wrote:
I have some functions for which I want to find the nicest possible
combination of performance and usability. I have two suggestions as to how
they should be defined.
"Classic" style:
real myFunction(real arg, int someParam, inout real aReturnValue)
{
declare temporary variables;
do some calculations;
store a return value in aReturnValue;
return main return value;
}
The user-friendly way, where the function is encapsulated in a class:
class MyFunctionWorkspace
{
declare private temporary variables;
real anotherReturnValue;
this (int someParam)
{ ... }
real myFunction(real arg)
{
do some calculations;
store a return value in aReturnValue;
return main return value;
}
}
I'm sure a lot of people will disagree with me on this, but let me first say
why I think the last case is more user-friendly. For one thing, the same
class can be used over and over again with the same parameter(s). Also, the
user only has to retrieve aReturnValue if it is needed. If there are many
such "additional" inout parameters which are seldom needed, it gets tedious
to declare variables for them every time the function is called. I could
overload the function, but this also has drawbacks if there are several
inout parameters with the same type.
My questions are:
- If I do like in the second example above, and reuse temporary variables
instead of allocating them every time the function is called, could this way
also give the best performance? (Yes, I know this is bad form...)
...or, if not...
- If I (again in the second example) move the temporary variables inside the
function, so they are allocated on the stack instead of the heap (?), will
this improve or reduce performance?
I could write both types of code and test them against each other, but I am
planning to use the same style for several different functions in several
modules, and want to find the solution which is generally the best one.
Any gains you get from skipping the initial calculations will be
swiftly cut down by the cost of heap allocation and cache misses, if
you allocate this object several times.
OK. But if the object is allocated once (or seldomly, at least), and I
allocate any working variables on the stack, then the second case may
not be half bad?
A much better way to get the usability of the latter with the better
performance of the former is to use a struct instead of a class. I
highly doubt you'll be needing to inherit these "operation objects"
anyway. The struct will be allocated on the stack, and you still get
all the usability.
Thanks, I hadn't even thought of that! :) This could certainly be a
solution. There are two problems, however:
1) In D1, structs don't have constructors, which could again make the
initial parameter setting a tedious task. But this is not a big problem,
as I could just define a static opCall for each struct as a kind of
constructor.
2) Bigger problem: I was kinda hoping that all the functions could
implement a common interface, so I can use them in generic algorithms.
This could possibly be done with structs using templates, but plain old
interfaces would be a cleaner solution.
-Lars