I just noticed that when a method has a ref parameter for a struct, it doesn't
get inlined:
union Matrix4x4 {
struct { float _11, _12, ...}
float[4][4] m;
float[16] v;
Matrix4x4 opMul(const ref Matrix4x4 m) const { ... }
void opMulAssign(const ref Matrix4x4 m) { this = opMul(m); }
void Translate(float x, float y, float z) {
const m = GetTranslation(x, y, z);
opMulAssign(m);
}
static Matrix4x4 GetTranslation(float x, float y, float z) { ... }
}
// RVO and inlining works like a charm here
Matrix4x4 m1 = Matrix4x4.GetTranslation(10, 0, 0);
// No inlining whatsoever here
m1.Translate(0, 1, 0);
I know in C++ when passing by reference (const Matrix4x4& m) the code gets
inlned.
It's even worse when using the in (I know it means const scope) storage class
for these members:
Matrix4x4 opMul(in Matrix4x4 m) const { ... }
void opMulAssign(in Matrix4x4 m) { this = opMul(m); }
void Translate(float x, float y, float z) {
opMulAssign(GetTranslation(x, y, z));
}
Not only does it not get inlined, but the whole 64bytes of the struct is copied
into every stack frame using a bunch of MOVS instructions.
Isn't there a way to implement RVO to work on parameters (PVO?) too if the
storage is const? The compiler could even detect that GetTranslation() is going
to write to the stack frame of opMulAssign and inline the entire sequence. Even
in debug compiles you could skip the whole data copy thing.
For now I pass all my references to any struct larger than 8bytes in my code by
explicitely dereferencing (in Matrix4x4* m) to get the inline to work, but that
kind of kills the newer syntax of D for such things. I think this should be
left for compatibility with C and get the D storage classes working properly to
prevent having to use pointers all over D too.

Just voted, it should be marked as urgent, I can't even begin to imagine the
amount of code that will need to be converted back to D syntax once it is fixed.
Thanks.

Just to stress out how important this is; I have a small loop calculating a 3x2
rotation matrix used with either Direct2D or Cairo every 10ms which transform
the text "Hello World" in a window. CPU usage drops by 7-10% when using C style
pointers instead of D storage classes. I haven't even optimized with SSE and
whatnot yet, just removing the stack frame initialization overhead.
It would be way worse with the out storage class since the memory also has to
be zero filled, which is overkill to me since its much better to just throw an
error "out variable x used before initialization".

Just to stress out how important this is; I have a small loop calculating a
3x2 rotation matrix used with either Direct2D or Cairo every 10ms which
transform the text "Hello World" in a window. CPU usage drops by 7-10% when
using C style pointers instead of D storage classes. I haven't even optimized
with SSE and whatnot yet, just removing the stack frame initialization
overhead.<

Are you in a situation where you use the LDC compiler?
Bye,
bearophile

Just to stress out how important this is; I have a small loop calculating a
3x2 rotation matrix used with either Direct2D or Cairo every 10ms which
transform the text "Hello World" in a window. CPU usage drops by 7-10% when
using C style pointers instead of D storage classes. I haven't even optimized
with SSE and whatnot yet, just removing the stack frame initialization
overhead.<

Are you in a situation where you use the LDC compiler?
Bye,
bearophile

DMD 2.031 here on windows 7 x64, I'm writing a Direct2D backend for my display
package. I don't mind not having 64-bit support for now, but I definitely care
about being on the bleeding edge of the D2 language. I also use the same
compiler on Ubuntu.
I use a customized runtime forked from D1 in '06 and almost entirely rewritten
kepping up to date with every new D release. I dropped support for D1 last
year. Last I heard LDC only supported D1 under unix, haven't checked it in a
while.

DMD 2.031 here on windows 7 x64, I'm writing a Direct2D backend for my display
package. I don't mind not having 64-bit support for now, but I definitely care
about being on the bleeding edge of the D2 language. I also use the same
compiler on Ubuntu.
I use a customized runtime forked from D1 in '06 and almost entirely rewritten
kepping up to date with every new D release. I dropped support for D1 last
year. Last I heard LDC only supported D1 under unix, haven't checked it in a
while.<

Yes but that would be a logic error from the programmer, as it would be
possible to do the very same thing had foo been declared as void foo(in S* s).
Isn't it possible to make 'const ref S' or 'in S' generate the same machine
code as 'in S*'? To me it would seem the semantics of the two are the same,
with 'const S*' being useful syntax for C compatibility while 'in S' and 'const
ref S' are both D syntax.
I don't use ref and out whatsoever in D because of their overhead and inability
to inline, which is sad because the first time I read about D I pictured having
every single parameter in my programs having at least one of in, ref or out and
finally saying bye bye to pointers.

Isn't it possible to make 'const ref S' or 'in S' generate the same
machine code as 'in S*'? To me it would seem the semantics of the two
are the same, with 'const S*' being useful syntax for C compatibility
while 'in S' and 'const ref S' are both D syntax.

The thing about const is it only specifies a read only view of an
object, it does *not* specify that the referenced object will not
change. That is why pass by value cannot be "optimized" to be pass by
reference.

Isn't it possible to make 'const ref S' or 'in S' generate the same
machine code as 'in S*'? To me it would seem the semantics of the two
are the same, with 'const S*' being useful syntax for C compatibility
while 'in S' and 'const ref S' are both D syntax.

The thing about const is it only specifies a read only view of an
object, it does *not* specify that the referenced object will not
change. That is why pass by value cannot be "optimized" to be pass by
reference.

Isn't it possible to make 'const ref S' or 'in S' generate the same
machine code as 'in S*'? To me it would seem the semantics of the two
are the same, with 'const S*' being useful syntax for C compatibility
while 'in S' and 'const ref S' are both D syntax.

The thing about const is it only specifies a read only view of an
object, it does *not* specify that the referenced object will not
change. That is why pass by value cannot be "optimized" to be pass by
reference.

Ok, I understand why it cant be done for 'in S' but I don't see why 'const ref
S' cannot have the same semantics as 'in S*', unless 'ref' doesn't mean that
the struct is implicitly dereferenced.
Here is some code to illustrate my point of view:
struct S { int i; }
S s;
void Stuff() { s.i++; }
void Foo(in S* s) {
writefln(s.i);
Stuff();
writefln(s.i);
}
void Bar(const ref S s) {
writefln(s.i);
Stuff();
writefln(s.i);
}
int main() {
// Those both do the exact same thing
Foo(&s);
Bar(s);
}
If they are meant to have different semantics, then when is a good time to use
ref? It would seem to me 'in S*' and 'S*' carry both behaviors you want in a
referenced parameter: const and mutable. In any case only the reference is
passed by value, not the struct itself.
If the method calls another method which modifies the const view on the
reference, then it should be a logic error from the programmer (good old
shooting yourself in the foot) without the compiler getting in the way. Making
fool-proof language semantics is a good idea, but IMO it shouldn't impact
performance, or else any bit of code looking for time critical performance will
never use the syntax that makes D shine, and a lot of confusion will spread
around as both types of syntax are used. It also makes it confusing to
interface with IDL.
Alls I'm suggesting is that 'const ref S' and 'ref S' generate the same machine
code as 'in S*' and 'S*', which would prevent us from using different syntax to
get the performance boost, when in the end the intended behavior is the same.

You're addressing the 'const' issue, but you haven't addressed the
OP's issue: that 'ref', for whatever reason, prevents inlining. Const
aside, why is this so?

Well I'm glad it's that simple, and I'm sure Jeremie is too ;)

There are a lot of D specific optimization opportunities that are left
undone for now.

Why?
Seeing D as "a systems language with features form high-level languages
but without the performance penalty so you can prefer it over
C/C++/Java/C# etc.", if D's performance isn't that good then there's not
much competition for people coming from either sides that expect high
performance.
bearophile and others from time to time complain about performance
issues in D, just because D promises performance. I think this is more
important that adding more features that won't give you higher performance.
performance
(sorry, had to repeat that word one more time :-P)

There are a lot of D specific optimization opportunities that are
left undone for now.

Which of the thousand things people want done in D should be done first?

Those that you feel like doing first.
Ok, you win. :-)
(I use the same reasoning most of the time when coding Descent)

<g> But I'm not kidding about the thousand things. There are more than
that in Bugzilla.

The core feature set should be more important for now, since they drive D2
closer to a stable specification, and I know how adding new features can break
optimizations and whatnot.
I would rather see T[new] arrays and working shared qualifiers myself. However,
proper ref semantics would also allow us to switch back from C to D syntax for
these.
Maybe I should get familiar with dmd2's source and see if I can contribute to
those issues once I get more free time, but even in its current development
state, I have more fun coding in D than I ever had in C or C++.

You said "which of the thousand things people want done should be done
first?" And we already tried to solve this problem with the Bugzilla
voting feature. Has it been working out well? Have the issues that
people want to get fixed been getting more attention than the others?

I'll let you decide that based on stats from Bugzilla and the changelog.
I suspect about everyone's conclusion on that would be different.
I just wish to point out that while ref inlining has been pointed out as
very important here, that isn't reflected in the Bugzilla votes. In
other words, while the votes are important, they are not the only
indicator of what is important.

There are a lot of D specific optimization opportunities that are left
undone for now.

I'd say things should get a priority bump if they're either:
1. Major breaking changes. Let's get these out of the way so the spec can
stabilize.
2. Bugs that substantially reduce the functionality of new/D-specific features,
thus preventing comments on how these features might be improved, etc.
3. High bang for buck, i.e. something that, given the background of the person
implementing it, would help a lot of people/situations for relatively little
effort.
For the most part, I agree that performance optimizations can wait. It's just
that, when ref params are used at a very low level in Phobos (think swap() ),
and
it's easy for someone with the right background to implement ref inlining, that
makes it a very high bang for buck optimization.

I think these kinds of limitations make people more sour than others
because D lacks a manual inlining mechanism, with the explanation that
the compiler knows how to inline better.

C++ lacks it, too. The "inline" keyword is a hint which the compiler is
free to ignore - the C++ compiler can also inline functions with no such
annotation.

Clearly, the compiler isn't
there yet, and I understand why, I just wanted to bring to light why
this might be a thorn in some sides.

Off the top of my head, I could list at least a hundred things people
list as why they don't use D. I'd like to knock all those reasons down,
and each release makes progress in doing so.
But it is worthwhile to bring these things up. It helps in trying to
gauge their relative importance.

You said "which of the thousand things people want done should be done
first?" And we already tried to solve this problem with the Bugzilla
voting feature. Has it been working out well? Have the issues that
people want to get fixed been getting more attention than the others?

I'll let you decide that based on stats from Bugzilla and the changelog. =

suspect about everyone's conclusion on that would be different.
I just wish to point out that while ref inlining has been pointed out as
very important here, that isn't reflected in the Bugzilla votes. In other
words, while the votes are important, they are not the only indicator of
what is important.

There are a lot of D specific optimization opportunities that are
left
undone for now.

Why?

Which of the thousand things people want done in D should be done
first?

Those that you feel like doing first.
Ok, you win. :-)
(I use the same reasoning most of the time when coding Descent)

<g> But I'm not kidding about the thousand things. There are more than
that
in Bugzilla.

So uh, how's the Bugzilla voting system working out then?

Inlining of functions with ref arguments has gotten 0 votes.

You said "which of the thousand things people want done should be done
first?" And we already tried to solve this problem with the Bugzilla
voting feature. Has it been working out well? Have the issues that
people want to get fixed been getting more attention than the others?

You said "which of the thousand things people want done should be done
first?" And we already tried to solve this problem with the Bugzilla
voting feature. Has it been working out well? Have the issues that
people want to get fixed been getting more attention than the others?

I'll let you decide that based on stats from Bugzilla and the changelog.
I suspect about everyone's conclusion on that would be different.
I just wish to point out that while ref inlining has been pointed out as
very important here, that isn't reflected in the Bugzilla votes. In
other words, while the votes are important, they are not the only
indicator of what is important.

If you've been consistently following the voting system as an indicator,
people would just go to bugzilla and vote for this ref inlining bug
instead of shouting here and playing the attracting Walter game. And you
don't need to play the identifying the most important bug game either.
--
╩╣Ë├ Opera Ş´├ŘđďÁ─ÁšÎËË╩╝■┐═╗ž│╠đ˛: http://www.opera.com/mail/

You're addressing the 'const' issue, but you haven't addressed the
OP's issue: that 'ref', for whatever reason, prevents inlining. Const
aside, why is this so?

shame to have this hanging around in a language whose biggest selling
point over the competition is speed. It's been shown many times that
DMD's failure to inline ref args has significant impact (~10%) on the
performance of numerical code. If you can easily give these kinds of
code a 10% boost without too much effort then that's a big win in my
opinion.
--bb

yourself in the 'us' inside "let's", right?

I'm actually surprised Don hasn't jumped on this one, given that it's
primarily numerical code that it seems to be affecting.

I imagined it would require deep understanding of the compiler back-end,
which I don't currently have. Based on Walter's comment, perhaps it's
not so difficult. I do have an FP performance patch in the next DMD.
But I've been focussing more on ICE bugs and CTFE, which have been
annoying me more.

If I were
still at my old job using D heavily, I would probably take a whack at
fixing this one, just because it has been such an annoyance to me. I
put up with it figuring it would be fixed someday, and I assumed there
must be something tricky about it or else it would have been done
already. But given Walter's answer just now, it sounds like a quick
fix for him or someone else familiar with the compilers internals.
--bb

You're addressing the 'const' issue, but you haven't addressed the
OP's issue: that 'ref', for whatever reason, prevents inlining. Const
aside, why is this so?

Because I never updated the inlining code to handle it.

Wow. That's it? So let's get it done already! This is really a
shame to have this hanging around in a language whose biggest selling
point over the competition is speed. It's been shown many times that
DMD's failure to inline ref args has significant impact (~10%) on the
performance of numerical code. If you can easily give these kinds of
code a 10% boost without too much effort then that's a big win in my
opinion.
--bb

You're addressing the 'const' issue, but you haven't addressed the
OP's issue: that 'ref', for whatever reason, prevents inlining. Const
aside, why is this so?

Because I never updated the inlining code to handle it.

Wow. That's it? So let's get it done already! This is really a
shame to have this hanging around in a language whose biggest selling
point over the competition is speed. It's been shown many times that
DMD's failure to inline ref args has significant impact (~10%) on the
performance of numerical code. If you can easily give these kinds of
code a 10% boost without too much effort then that's a big win in my
opinion.
--bb

Ok.. so we should expect a patch from you sometime soon? You did include
yourself in the 'us' inside "let's", right?

You're addressing the 'const' issue, but you haven't addressed the
OP's issue: that 'ref', for whatever reason, prevents inlining. Const
aside, why is this so?

Because I never updated the inlining code to handle it.

Wow. =A0That's it? =A0So let's get it done already! =A0This is really a
shame to have this hanging around in a language whose biggest selling
point over the competition is speed. =A0 It's been shown many times that
DMD's failure to inline ref args has significant impact (~10%) on the
performance of numerical code. =A0If you can easily give these kinds of
code a 10% boost without too much effort then that's a big win in my
opinion.
--bb

Ok.. so we should expect a patch from you sometime soon? =A0You did inclu=

yourself in the 'us' inside "let's", right?

I'm actually surprised Don hasn't jumped on this one, given that it's
primarily numerical code that it seems to be affecting. If I were
still at my old job using D heavily, I would probably take a whack at
fixing this one, just because it has been such an annoyance to me. I
put up with it figuring it would be fixed someday, and I assumed there
must be something tricky about it or else it would have been done
already. But given Walter's answer just now, it sounds like a quick
fix for him or someone else familiar with the compilers internals.
--bb

You're addressing the 'const' issue, but you haven't addressed the
OP's issue: that 'ref', for whatever reason, prevents inlining. Const
aside, why is this so?

Because I never updated the inlining code to handle it.

Well I'm glad it's that simple, and I'm sure Jeremie is too ;)

There are a lot of D specific optimization opportunities that are left
undone for now.

Why?
Seeing D as "a systems language with features form high-level languages b=

without the performance penalty so you can prefer it over C/C++/Java/C#
etc.", if D's performance isn't that good then there's not much competiti=

for people coming from either sides that expect high performance.
bearophile and others from time to time complain about performance issues=

D, just because D promises performance. I think this is more important th=

adding more features that won't give you higher performance.

I think it's perfectly justified to put off optimizations that are
tricky or only pay off in odd circumstances. But from Walter's
comment it sounds like this one shouldn't be any harder than enabling
the pointer inlining path for ref args too. And the payoff would be
decent.
--bb

You're addressing the 'const' issue, but you haven't addressed the
OP's issue: that 'ref', for whatever reason, prevents inlining. Const
aside, why is this so?

There are a lot of D specific optimization opportunities that are left
undone for now.

This is fine with me. I think the OP just wants to be sure that not
inlining functions with ref args isn't a design decision.
I think these kinds of limitations make people more sour than others
because D lacks a manual inlining mechanism, with the explanation that the
compiler knows how to inline better. Clearly, the compiler isn't there
yet, and I understand why, I just wanted to bring to light why this might
be a thorn in some sides.
-Steve