Delegate perfomance (outrage was redherring)
Justin Johansson
no at spam.com
Thu Oct 15 21:21:27 PDT 2009
bearophile Wrote:
> Justin Johansson:
>
> > downs:
> > > Also I have no idea what you mean. Should delegate _values_ be heap allocated?! That'd be insanity. Also, I'm fairly sure you're wrong. The stack is relatively likely to be in the CPU cache. A random pointer dereferencing .. isn't. Also, do you really want to heap even more work on the ailing GC?
> >
> > I will be bold and say yes to off-stack allocation,
> > whether that be in the general heap or other (and probably other to avoid an "ailing CG").
>
> This is a nice situation: with just 10-20 minutes of experimental tests (that later you have to show us) you can show us you are right, or wrong.
>
> Bye,
> bearophile
Fresh light of morning ...
I'm really glad to have brought this up as I would not have bothered to revisit a performance
issue that I had in porting some C++ to D (and this was not looking good for D at first sight).
As it turns out though, my initial fear about the .sizeof delegate was unfounded as the performance
bottleneck was in an loop inside of a method taking what was effectively a callback parameter.
The C++ design was basically implementing a classical visitor pattern over a collection.
In porting to D I had a choice of either doing a one-for-one translation of the C++ classes or
redesigning using D delegates.
This morning I boiled the problem down to the simplest possible with the two forms and
benchmarked these. From the code I have reproduced below, clearly the
issue is nothing to do with the cost of instantiating a delegate or visitor object. That turns
out to be a one time cost and irrelevant given where the iteration actually occurs.
So while this isn't the proof or disproof that bearophile asked for, this turns out to be
a clear demonstration of the performance-enhancing power of D delegates over an
otherwise ingrained C++ thinking approach.
I'm impressed. (Hope that statement isn't too emotional :-)
#! /opt/dmd1/linux/bin/rdmd -I/opt/dmd1/src/phobos -L-L/opt/dmd1/linux/lib -release
import std.perf, std.stdio;
class SetOfIntegers
{
private int from, to;
this( int from, int to) {
this.from = from;
this.to = to;
}
int forEach( int delegate( int x) apply) {
for (auto i = from; i <= to; ++i) {
apply( i);
}
return 0;
}
int forEach( Visitor v) {
for (auto i = from; i <= to; ++i) {
v.visit( i);
}
return 0;
}
}
class Visitor
{
abstract int visit( int x);
}
class MyVisitor: Visitor
{
int visit( int x) { return 0; }
}
void test1( SetOfIntegers s, Visitor v)
{
auto pc = new PerformanceCounter();
pc.start();
scope(exit) {
pc.stop();
writefln( "Using D style delegate callback: %d msec", pc.milliseconds());
}
s.forEach( &v.visit);
}
void test2( SetOfIntegers s, Visitor v)
{
auto pc = new PerformanceCounter();
pc.start();
scope(exit) {
pc.stop();
writefln( "Using C++ style virtual callback: %d msec", pc.milliseconds());
}
s.forEach( v);
}
void main() {
writefln( "Delegates vs virtual function callbacks");
writefln();
SetOfIntegers s = new SetOfIntegers( 1, 10000000);
Visitor v = new MyVisitor();
for (auto i = 0; i < 10; ++i) {
test1( s, v);
test2( s, v);
writefln();
}
writefln();
}
$ ./perf.d
Delegates vs virtual function callbacks
Using D style delegate callback: 121 msec
Using C++ style virtual callback: 146 msec
Using D style delegate callback: 121 msec
Using C++ style virtual callback: 147 msec
Using D style delegate callback: 120 msec
Using C++ style virtual callback: 145 msec
Using D style delegate callback: 121 msec
Using C++ style virtual callback: 145 msec
Using D style delegate callback: 120 msec
Using C++ style virtual callback: 145 msec
Using D style delegate callback: 120 msec
Using C++ style virtual callback: 147 msec
Using D style delegate callback: 121 msec
Using C++ style virtual callback: 147 msec
Using D style delegate callback: 121 msec
Using C++ style virtual callback: 147 msec
Using D style delegate callback: 121 msec
Using C++ style virtual callback: 146 msec
Using D style delegate callback: 121 msec
Using C++ style virtual callback: 147 msec
Sweet.
cheers
Justin Johansson
More information about the Digitalmars-d
mailing list