scope, inline, optimizations, scoped attributes

bearophile bearophileHUGS at lycos.com
Wed Aug 5 07:06:46 PDT 2009


In D there's no "inline" (even if it sometimes useful, see the pragma(allow_inline) of LDC, that's useful to force the inlining of functions that contain asm) because compilers are today regarded as smart enough to inline functions automatically when they see it's an advantage (sometimes they are wrong, it's an heuristics).

But D contains "scope" to suggest the compiler to stack allocate a class instance. Recently LDC is (sometimes) able to find by itself when an object behaves well enough to perform its automatic and invisible scoping (in such situation LDC adds an invisible stack-allocated variable that's the reference to the stack-allocated object, such reference is also used if you reassign the reference). So eventually D2 may choose to deprecate this usage of "scope" leaving such decision fully to the compiler, as in the inline case, reducing the work of the programmer a bit. Java compilers too perform such automatic stack allocation (and HotSpot is a bit better than LDC still in such regard, but I have a simple idea that may put LDC almost on par on this, http://www.dsource.org/projects/ldc/ticket/339 ).

About this topic, time ago some people have asked for a way to add "scope" to object class members, like this:

class Foo {
    int x;
    this(int xx) { this.x = xx; }
}

class Bar {
    scope Foo f; // ***
    int y;
    this(int xx, int yy) {
        this.f = new Foo(xx);
        this.y = yy;
    }
}

void main() {
    auto b = new Bar(10, 20);
    printf("%d %d\n", b.f.x, b.y);
}


This kind of optimization can be useful, this is shown in an example of small raytracing benchmark (I can offer all the code if you need it):

Timings, seconds, best of 3, on a 32 bit Ubuntu-like Linux:
  ray1_scoped_cpp  7.99
  ray1_d           8.51 (LDC Aug 3 2009)
  ray1_cpp         8.66

In "ray1_scoped_cpp" an object that's a class attribute is scoped, in ray1_cpp it is not as in the D code (Walter once said that D is slower than C++: it's often no longer true if you use LDC and if the code is the "same" (same = after compiler optimizations)).


Instead of adding "scope" to Foo f; inside Bar, a different possibility is to add LDC (and other future _D1_ compilers) a way to perform such optimization by themselves, in a transparent way (such "transparency" is sometimes dangerous, also because abstractions sometimes leak, but I assume it may be worth it anyway). This is not an easy thing to implement, but I think it can be done. The size of the class changes, the position of its fields changes, etc. There are some things that have to be special-cased to allow this optimization to produce programs that work correctly. An alternative solution that probably requires less special-casing is to add an invisible field to the class that has such scoped object member, this invisible field is the reference, that can be reassigned, etc. (Even with this extra field I think it can result as an optimization still, because there's more cache coherence, less total memory allocated, LDC is probably able to optimize away some deferences of this class reference, etc).

Bye,
bearophile



More information about the Digitalmars-d mailing list