Ranges, Performance, and opApply

Martin Nowak dawg at dawgfoto.de
Mon Oct 31 15:23:22 PDT 2011


On Mon, 31 Oct 2011 13:56:21 +0100, Steven Schveighoffer  
<schveiguy at yahoo.com> wrote:

> On Sun, 30 Oct 2011 15:23:59 -0400, dsimcha <dsimcha at yahoo.com> wrote:
>
>> On 10/30/2011 3:09 PM, Andrei Alexandrescu wrote:
>>>> As the opApply body can never be inlined it is a worse choice in  
>>>> general.
>>>
>>> That was my intuition too.
>>>
>>>
>>> Andrei
>>
>> Just for future reference, LDC **DOES** sometimes inline opApply bodies.
>
> The compiler should almost always be able to inline opApply, as the code  
> for the opApply body is always available.
>
> There are few exceptions, such as when opApply is not final, or when  
> it's recursive.  I wonder if even in these cases, some sort of "virtual  
> inlining" such as pushing the code onto the stack and avoiding using  
> function calls would be possible (speaking from naivety, maybe this does  
> nothing).  Being able to exploit the fact that a delegate literal is  
> always fully available would be nice.
>
> Indeed, opApply should beat the pants off of ranges when the range  
> primitives are virtual functions.  But ranges should win when inlining  
> is possible in some cases.
>
> There are always going to be use cases for opApply that ranges cannot  
> duplicate (such as recursion), and vice versa (such as parallel  
> iteration).
>
> -Steve

Inlining the body would necessitate one parameterized function
per caller. Quite a lot of code and doesn't even have defined mangling,  
does it?
It's a different topic when both, the opApply function and the body are
inlined at the caller site.
Also when inlining the body it is much more difficult to assign registers
to variables from the calling stack unless you can prove that nobody can
refer to them.

I think a better approach is to revive the templated 'opApply(alias fbody)'
idea alternatively to the delegated one.
But there are currently too many issues to do this.

Constructing similar functionality requires quite some C++-ish gymnastics.
Partly due to bugs and for reasons discussed here:
http://d.puremagic.com/issues/show_bug.cgi?id=5710.
----
import std.range, std.stdio;

struct Context
{
     // doesn't even work as static method
     alias Context_forEach forEach;
     uint[] data;
}

// doesn't work at module scope when erroneously prefixed with static ???
/*static*/
void Context_forEach(alias fbody)(ref Context self)
{
     foreach(e; self.data)
         fbody(e);
}

void main()
{
     size_t sum;
     auto ctx = Context(array(iota(0U, 500U)));
     Context.forEach!(
     (a)
     {
         sum += a;
     }
     )(ctx);
     writeln(sum);
}

martin


More information about the Digitalmars-d mailing list