Christopher Wright:
> > Certainly agreed on virtual calls: on my machine, I timed a simple
> > example as executing 65 interface calls per microsecond, 85 virtual
> > calls per microsecond, and 210 non-member function calls per
> > microsecond. So you should almost never worry about the cost of
> > interface calls since they're so cheap, but they are 3.5 times slower
> > than non-member functions.
The main problem of virtual calls in D are the missed inlining opportunities.
------------
Andrei Alexandrescu:
> I seem to recall that
> interface dispach in D does a linear search in the interfaces list, so
> you may want to repeat your tests with a variable number of interfaces,
> and a variable position of the interface being used.
The following is a D port of the well known "Richards" benchmark. This specific version is object oriented, its classes are final (otherwise the code gets quite slower with LDC) and it has getters/setters. It contains an interface:
http://codepad.org/kO3MJK60
You can run it at the command line giving it 10000000.
On a Celeron 2 GHz if you replace the interface with an abstract class the running time goes from 2.16 to 1.58 seconds, compiled with:
ldc -O5 -release -inline
Compiled with DMD the running time seems about unchanged. I have no idea why. Maybe some of you can tell me.
In a day or two I'll release many more timings and tests about this Richards benchmark.
Bye,
bearophile

On 28/09/2009 15:28, Jeremie Pelletier wrote:
>>
>> here's a type-safe alternative
>> note: untested
>>
>> struct Vec3F {
>> float[3] v;
>> alias v[0] x;
>> alias v[1] y;
>> alias v[2] z;
>> }
>>
>> D provides alignment control for structs, why do we need to have a
>> separate union construct if it is just a special case of struct
>> alignment?
>
> These aliases won't compile, and that was only one out of many union uses.
what other use cases for unions exist that cannot be redesigned in a
safer way?
>
>> IMO the use cases for union are very rare and they all can be
>> redesigned in a type safe manner.
>
> Not always true.
>
>> when software was small and simple, hand tuning code with low level
>> mechanisms (such as unions and even using assembly) made a lot of
>> sense. Today's software is typically far more complex and is way to
>> big to risk loosing safety features for marginal performance gains.
>>
>> micro optimizations simply doesn't scale.
>
> Again, that's a lazy view on programming. High level constructs are
> useful to isolate small and simple algorithms which are implemented at
> low level.
One way to define programming is "being lazy". You ask the machine to do
your work since you are lazy to do it yourself.
your view above about simple algorithms which are implemented at low
level is exactly the place where we disagree.
Have you ever heard of Stalin (i'm not talking about the dictator)?
I was pointing to a trade off at play here:
you can write low level hand optimized code that is hard to maintain and
reason about (for example, providing formal proof of correctness). You
gained some small, non scalable performance gains and lost on other
fronts like proving correctness of your code.
the other way would be to write high level very regular code that can be
maintained, easier to reason about and leave optimization to the tools.
granted, there could be some initial performance hit compared to the
previous approach but this is more portable:
hardware changes do not affect code, you just need to re-run the tool.
new optimization techniques can be employed by running a newer version
of the tool, etc.
I should also note that the second approach is already applied by
compilers. unless you use inline ASM, the compiler will not use the
entire ASM instruction set which contains special cases for performance
tuning.
>
> These aren't just marginal performance gains, they can easily be up to
> 15-30% improvements, sometimes 50% and more. If this is too complex or
> the risk is too high for you then don't use a systems language :)
your approach makes sense if your are implementing say a calculator.
It doesn't scale to larger projects. Even C++ has overhead compared to
assembly yet you are writing performance critical code in c++, right?
Java had a reputation of being slow yet today performance critical
servers are written in Java and not in C++ in order to get faster
execution.

On Mon, 28 Sep 2009 15:35:07 -0400, Jesse Phillips
<jesse.k.phillips+d@gmail.com> wrote:
> language_fan Wrote:
>
>> Have you ever used functional languages? When you develop in Haskell or
>> SML, how often you feel there is a good change something will be
>> initialized to the wrong value? Can you show some statistics that show
>> how unsafe this practice is?
>
> So isn't that the question? Does/can "default" (by human or machine)
> initialization create an incorrect state? If it does, do we continue to
> work as if nothing was wrong or crash? I don't know how often the
> initialization would be incorrect, but I don't think Walter is concerned
> with it's frequency, but that it is possible.
It creates an invalid, non-compiling program.
It's simple:
If initialization doesn't make sense, don't use non-nullable type.
If initialization makes sense, use non-nullable type, initialize with the
correct value.
In case 1, we are back to current behavior, no problem (in Walter's eyes).
In case 2, we eliminate any possible crash due to non-initialization.
The subtle difference is the *default*. If non-null is the default, then
you haphazardly write code like this:
Object o;
And you get a compile error "error, please initialize o or declare as
Object? o". It makes you look at the line and say "hm... does it make
sense to initialize there?" and you either put an initializer or you
change it to
Object? o;
And move on.
90% of the time, you write something like:
auto x = new Object();
and you don't even have to think about it. The compiler tells you when
you got it wrong, and usually you then get it right after a moment of
thought.
At least, that has been my experience with C# (granted, it uses flow
analysis, not non-nullable defaults). And I very seldom have null
exception errors in my C# programs (they do happen, but of course, I get a
nice stack trace). Compare that to D, where I build my program and get:
# ./program_that_I_just_spent_1_week_writing_and_getting_to_compile
Segmentation fault.
#
I'd rather spend an extra 5 minutes having D compiler complain about
initialization than face the Segmentation fault error search.
The thing is, I don't want D to cater to the moronic programmers that say
"what? I need to initialize, ok, um.. here's a dummy object". I want it
to cater to *me* and prevent *me* from making simple errors where I
obviously should have known better, but accidentally left out the
initializer.
It's like the whole allowing object == null problem (coincidentally,
resulting in the same dreaded error). Once Walter implemented the
compiler that flagged them all, he discovered Phobos had several of those
*obviously incorrect* statements. Hm... maybe he should do the same with
this... Maybe someone who can hack the compiler can do it for him! Any
takers?
-Steve
P.S. I never make the object == null mistake anymore. The compiler has
trained me :)

Hello Manfred_Nowak,
> BCS wrote:
>
> [...]
>
>> I wouldn't want to hire a programer that *habitually* (and
>> unnecessarily) hacks past a feature designed to prevent bugs.
>>
> In the short time of an interview its not possible to test for habits
> (or necessarity) to hack past a feature designed to provent bugs.
Good point, I guess that all that is left would be to try and get a feel
for what they think of that kind of practice (give them something ugly that
works and ask "what do you think of this code?"). If they indicate they think
that kind of hacking a bad idea, then at least you can say they lied if you
have to get rid of them for that kind of things.

Mon, 28 Sep 2009 20:34:44 +0000, BCS thusly wrote:
> Hello Manfred_Nowak,
>
>> BCS wrote:
>>
>> [...]
>>
>>> I wouldn't want to hire a programer that *habitually* (and
>>> unnecessarily) hacks past a feature designed to prevent bugs.
>>>
>> In the short time of an interview its not possible to test for habits
>> (or necessarity) to hack past a feature designed to provent bugs.
>
> Good point, I guess that all that is left would be to try and get a feel
> for what they think of that kind of practice (give them something ugly
> that works and ask "what do you think of this code?"). If they indicate
> they think that kind of hacking a bad idea, then at least you can say
> they lied if you have to get rid of them for that kind of things.
At least in the companies I have worked in they briefly teach you their
stuff in 1-7 days and want to see some preliminary results. If you have
trouble writing any code, you have lost the job (there is a 6 month test
period or something similar so it is perfectly legal to kick him out if
he fails). Usually the schedules are tight so hiring a lazy bastard is
not worth the effort. Other ways to control the learning are working with
a more experienced pair (pair programming - ever heard of it?) and weekly
meetings.

Mon, 28 Sep 2009 15:35:07 -0400, Jesse Phillips thusly wrote:
> language_fan Wrote:
>
>> > Now if you really want to throw some sticks into the spokes, you
>> > would say that if the program crashes due to a null pointer, it is
>> > still likely that the programmer will just initialize/set the value
>> > to a "default" that still isn't valid just to get the program to
>> > continue to run.
>>
>> Why should it crash in the first place? I hate crashes. You liek them?
>> I can prove by structural induction that you do not like them when you
>> can avoid crashes with static checking.
>
> No one likes programs that crash, doesn't that mean it is an incorrect
> behavior though?
>
>> Have you ever used functional languages? When you develop in Haskell or
>> SML, how often you feel there is a good change something will be
>> initialized to the wrong value? Can you show some statistics that show
>> how unsafe this practice is?
>
> So isn't that the question? Does/can "default" (by human or machine)
> initialization create an incorrect state? If it does, do we continue to
> work as if nothing was wrong or crash? I don't know how often the
> initialization would be incorrect, but I don't think Walter is concerned
> with it's frequency, but that it is possible.
Value types can be incorrectly initialized and nobody notices. E.g.
int min;
foreach(int value; list)
if (value < min) min = value;
Oops, you forgot to define a flag variable or initialize to int.min (if
that is what you want). Even Java IDEs spot this error, but not D. The
flow analysis helps me in tremendous ways - I can fix the error
statically and boom, the software is suddenly again error free.
Now I can tell you, in functional languages there is no other way. All
initializations have to be correct, they are final, they are constants
and they can be initialized incorrectly. But there are some tools that
help in this. Functions can be automatically tested. Invariants, pre- and
post-conditions can be set. Still, I can even bet they are much safer
than D in every possible way. How is this possible?
It really depends on your subjective opinion whether you want a program
to segfault or spot a set of errors statically, and have illegally
behaving non-crashing programs. I say FFFFFFFFFFUUUUUUUUUUU every time I
experience a segfault. My hobby programs at home are not that critical,
and at work the critical code is *proven* to be correct so no need to
worry there.

Yigal Chripun:
>Have you ever heard of Stalin (i'm not talking about the dictator)?<
Stalin accepts only a certain subset of Scheme, you can't use some of the nicest things.
And while ShedSkin is slow, Stalin is really slow, so slow that compiling largish programs becomes not handy (I think times like 100 seconds for 500 lines-long programs, I don't know if such timings have improved in the meantime, I hope so).
> the other way would be to write high level very regular code that can be
> maintained, easier to reason about and leave optimization to the tools.
Life is usually a matter of finding a balance. If you care of performance you don't use Scheme, you use a handy language that doesn't force the compiler to work a LOT, for example C#.
Bye,
bearophile

Mon, 28 Sep 2009 22:33:26 +0000, language_fan thusly wrote:
> Value types can be incorrectly initialized and nobody notices. E.g.
>
> int min;
>
> foreach(int value; list)
> if (value < min) min = value;
> Now I can tell you, in functional languages there is no other way. All
> initializations have to be correct, they are final, they are constants
> and they can be initialized incorrectly. But there are some tools that
> help in this. Functions can be automatically tested. Invariants, pre-
> and post-conditions can be set. Still, I can even bet they are much
> safer than D in every possible way. How is this possible?
For instance if I use the example given above, I write it like this in a
functional language:
find_min:: Ord a => [a] -> Maybe a
find_min [] = Nothing
find_min (h:t) = Just $ foldl min h t
You can then use quickcheck to verify the result in some fancy way.
I just cannot think of any way how you could crash programs written in
this way. They are solid as a rock.

"language_fan" <foo@bar.com.invalid> wrote in message
news:h9relp$1ebg$4@digitalmars.com...
> Mon, 28 Sep 2009 22:33:26 +0000, language_fan thusly wrote:
>
>> Value types can be incorrectly initialized and nobody notices. E.g.
>>
>> int min;
>>
>> foreach(int value; list)
>> if (value < min) min = value;
>
>> Now I can tell you, in functional languages there is no other way. All
>> initializations have to be correct, they are final, they are constants
>> and they can be initialized incorrectly. But there are some tools that
>> help in this. Functions can be automatically tested. Invariants, pre-
>> and post-conditions can be set. Still, I can even bet they are much
>> safer than D in every possible way. How is this possible?
>
> For instance if I use the example given above, I write it like this in a
> functional language:
>
> find_min:: Ord a => [a] -> Maybe a
> find_min [] = Nothing
> find_min (h:t) = Just $ foldl min h t
>
> You can then use quickcheck to verify the result in some fancy way.
>
> I just cannot think of any way how you could crash programs written in
> this way. They are solid as a rock.
I'm not particulary accustomed to that sort of syntax. Am I correct in my
analysis that that essentially does something like this?:
// Assuming that:
// 1. Variables of type void could be declared and had value 'void'.
// 2. 'any(T,U,V)' was a "supertype" that can and must be one (and only one)
of T, U, or V.
immutable any(int,void) min(immutable any(int,void) a, immutable
any(int,void) b)
{
static if( is(typeof(a) == void) && is(typeof(b) == void) )
return void;
else static if( is(typeof(a) == int) && is(typeof(b) == void) )
return a;
else static if( is(typeof(a) == void) && is(typeof(b) == int) )
return b;
else
return a<b? a : b;
}
immutable any(int,void) findMin(immutable int[] list)
{
static if(list.length == 0)
return void;
else
return reduce!("min(a,b)")(list); // 'reduce' from phobos2
}

Mon, 28 Sep 2009 20:17:54 -0400, Nick Sabalausky thusly wrote:
> "language_fan" <foo@bar.com.invalid> wrote in message
> news:h9relp$1ebg$4@digitalmars.com...
>> Mon, 28 Sep 2009 22:33:26 +0000, language_fan thusly wrote:
>>
>>> Value types can be incorrectly initialized and nobody notices. E.g.
>>>
>>> int min;
>>>
>>> foreach(int value; list)
>>> if (value < min) min = value;
>>
>>> Now I can tell you, in functional languages there is no other way. All
>>> initializations have to be correct, they are final, they are constants
>>> and they can be initialized incorrectly. But there are some tools that
>>> help in this. Functions can be automatically tested. Invariants, pre-
>>> and post-conditions can be set. Still, I can even bet they are much
>>> safer than D in every possible way. How is this possible?
>>
>> For instance if I use the example given above, I write it like this in
>> a functional language:
>>
>> find_min:: Ord a => [a] -> Maybe a
>> find_min [] = Nothing
>> find_min (h:t) = Just $ foldl min h t
>>
>> You can then use quickcheck to verify the result in some fancy way.
>>
>> I just cannot think of any way how you could crash programs written in
>> this way. They are solid as a rock.
>
> I'm not particulary accustomed to that sort of syntax. Am I correct in
> my analysis that that essentially does something like this?:
>
> // Assuming that:
> // 1. Variables of type void could be declared and had value 'void'. //
> 2. 'any(T,U,V)' was a "supertype" that can and must be one (and only
> one) of T, U, or V.
>
> immutable any(int,void) min(immutable any(int,void) a, immutable
> any(int,void) b)
> {
> static if( is(typeof(a) == void) && is(typeof(b) == void) )
> return void;
> else static if( is(typeof(a) == int) && is(typeof(b) == void) )
> return a;
> else static if( is(typeof(a) == void) && is(typeof(b) == int) )
> return b;
> else
> return a<b? a : b;
> }
>
> immutable any(int,void) findMin(immutable int[] list) {
> static if(list.length == 0)
> return void;
> else
> return reduce!("min(a,b)")(list); // 'reduce' from phobos2
> }
Well to be honest, I thought I knew how to read D, but this is starting
to look a bit scary. It looks like it does almost the same. I just used
lists instead of arrays since they are the basic data type in functional
code. Second, the find_min accepted any type that implements the 'Ord'
class, i.e. supports the '<' relation, not only ints. I guess it could
be solved by changing some pieces of code to look like this:
> immutable any(T,void) findMin(T)(immutable T[] list) {
My original idea was to just show that it is much harder to make similar
kinds of errors with algebraic data types. I should have made a less
generic :-)