View mode: basic / threaded / horizontal-split · Log in · Help
September 28, 2009
Re: Null references redux + Cyclone
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
September 28, 2009
Re: Null references redux
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.
September 28, 2009
Re: Null references redux
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 :)
September 28, 2009
Re: OT: Management of Coders (was: Null references redux)
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.
September 28, 2009
Re: OT: Management of Coders (was: Null references redux)
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.
September 28, 2009
Re: Null references redux
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.
September 28, 2009
Re: Null references redux
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
September 28, 2009
Re: Null references redux
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.
September 29, 2009
Re: Null references redux
"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
}
September 29, 2009
Re: Null references redux
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 :-)
15 16 17 18 19 20 21 22 23
Top | Discussion index | About this forum | D home