April 23, 2015
On Thursday, 23 April 2015 at 14:55:42 UTC, Iain Buclaw wrote:
> There are two states each local variable can be assigned.
> 1. Used
> 2. Read
>
> int a = 1;  // a = Used
> return a;  // a = Read
> printf("%d\n", a);  // a = Read
> int b = a;  // b = Used, a = Read
> int c = void; // c = Unused
>
> If a variable is unused, it's a dead variable.  If a variable is used
> but not read, it's a dead variable. Simple. :-)

Proving how indexing of an array hits the array in a nontrivial loop is intractable for large N (any parameter you like).

(you also don't deal with binary true/false, but three outcomes: satisfiable, unsatisfiable and unknown)
April 23, 2015
On Thursday, 23 April 2015 at 14:50:26 UTC, John Colvin wrote:
> There are cases where you might really need to grab an extra 1-5%, at which point you are hand optimising and = void is a reasonable tool.

Well, it can be a lot more than 1-5% in special situations if you hand over a small header request with a bundled array to fill in, so "=void" can be important.

But the real down side by making automatic initialization part of the language semantics is that you cannot do machine verfication where you detect cases where you forgot actual initialization. E.g. indexing where you should start at 1 and not 0.

That's not so good for correctness.

It's the same issue with modular arithmetics which actually remove overflows from integer operations, but then you cannot use machine verification to detect overflow either (unless you are happy with a large number of false positives).

April 23, 2015
On 4/23/2015 1:10 AM, bearophile wrote:
> Walter Bright:
>
>> On 4/22/2015 2:58 PM, bearophile wrote:
>>> D is less stack-friendly than Ada (and probably Rust too),
>>
>> ??
>
> In Ada standard library you have safe fixed-size stack-allocated associative
> arrays. In D you can't even allocate safely a dynamically-sized 1D array on the
> stack, and forget about doing it for 2D. Enough said.

I used to use alloca() here and there, but eventually removed it all. The trouble is, there are three array sizes:

   a) 0
   b) 1
   c) arbitrarily large

Dynamic stack allocation works for none of them. What does work is a fixed size stack allocation with failover to using malloc/free, which is what Phobos' scopebuffer does. It's analogous to the "small string optimization".

I don't agree with your assessment at all.

April 23, 2015
On Thursday, 23 April 2015 at 18:37:47 UTC, Walter Bright wrote:
> On 4/23/2015 1:10 AM, bearophile wrote:
>> Walter Bright:
>>
>>> On 4/22/2015 2:58 PM, bearophile wrote:
>>>> D is less stack-friendly than Ada (and probably Rust too),
>>>
>>> ??
>>
>> In Ada standard library you have safe fixed-size stack-allocated associative
>> arrays. In D you can't even allocate safely a dynamically-sized 1D array on the
>> stack, and forget about doing it for 2D. Enough said.
>
> I used to use alloca() here and there, but eventually removed it all. The trouble is, there are three array sizes:
>
>    a) 0
>    b) 1
>    c) arbitrarily large
>
> Dynamic stack allocation works for none of them. What does work is a fixed size stack allocation with failover to using malloc/free, which is what Phobos' scopebuffer does. It's analogous to the "small string optimization".
>
> I don't agree with your assessment at all.

I used to think this was totally wrong, but over time I've come to see your point.

The ideal for me would be a dynamically sized stack array (C99 style, not alloca) with a compile-time maximum size. Then you wrap that in a library type that decides/defines what to do when the size is exceeded (e.g. move to GC heap a la scopeBuffer), but in practice it's not a big win over just stack allocating the maximum size all the time (again, like scopeBuffer).
April 23, 2015
On Thursday, 23 April 2015 at 18:37:47 UTC, Walter Bright wrote:
> On 4/23/2015 1:10 AM, bearophile wrote:
>> Walter Bright:
>>
>>> On 4/22/2015 2:58 PM, bearophile wrote:
>>>> D is less stack-friendly than Ada (and probably Rust too),
>>>
>>> ??
>>
>> In Ada standard library you have safe fixed-size stack-allocated associative
>> arrays. In D you can't even allocate safely a dynamically-sized 1D array on the
>> stack, and forget about doing it for 2D. Enough said.
>
> I used to use alloca() here and there, but eventually removed it all. The trouble is, there are three array sizes:
>
>    a) 0
>    b) 1
>    c) arbitrarily large
>
> Dynamic stack allocation works for none of them. What does work is a fixed size stack allocation with failover to using malloc/free, which is what Phobos' scopebuffer does. It's analogous to the "small string optimization".
>
> I don't agree with your assessment at all.

Is there a reason scopebuffer isn't part of the documentation?
April 23, 2015
On Thursday, 23 April 2015 at 20:40:36 UTC, John Colvin wrote:
> scopeBuffer), but in practice it's not a big win over just stack allocating the maximum size all the time (again, like scopeBuffer).

If you have a random distribution of sizes then allocating the maximum will use twice as much memory. That affects cache performance.
April 23, 2015
On Thursday, 23 April 2015 at 18:37:47 UTC, Walter Bright wrote:
> On 4/23/2015 1:10 AM, bearophile wrote:
>> Walter Bright:
>>
>>> On 4/22/2015 2:58 PM, bearophile wrote:
>>>> D is less stack-friendly than Ada (and probably Rust too),
>>>
>>> ??
>>
>> In Ada standard library you have safe fixed-size stack-allocated associative
>> arrays. In D you can't even allocate safely a dynamically-sized 1D array on the
>> stack, and forget about doing it for 2D. Enough said.
>
> I used to use alloca() here and there, but eventually removed it all. The trouble is, there are three array sizes:
>
>    a) 0
>    b) 1
>    c) arbitrarily large
>
> Dynamic stack allocation works for none of them. What does work is a fixed size stack allocation with failover to using malloc/free, which is what Phobos' scopebuffer does. It's analogous to the "small string optimization".
>
> I don't agree with your assessment at all.

For arbitrary large, you can always do something like :

Item* itemPtr = (arbitrarylarge < thresold)
  ? alloca(arbitrarylarge)
  : GC.alloc(arbitrarylarge);

One extra check compared to a heap allocation is not going to make things terrible, and it is likely to be very predictible anyway (most arbitrarylarge size are actually small in practice).

The compiler could even do it at optimizer level.
April 24, 2015
On 4/23/2015 2:54 PM, weaselcat wrote:
> Is there a reason scopebuffer isn't part of the documentation?

Everyone hated it :-) but me.
April 24, 2015
On 4/23/2015 3:11 PM, deadalnix wrote:
> For arbitrary large, you can always do something like :
>
> Item* itemPtr = (arbitrarylarge < thresold)
>    ? alloca(arbitrarylarge)
>    : GC.alloc(arbitrarylarge);
>
> One extra check compared to a heap allocation is not going to make things
> terrible, and it is likely to be very predictible anyway (most arbitrarylarge
> size are actually small in practice).

You can, but it just doesn't pay off. Even if you found a case that did, it doesn't mean it pays off in general, and so would be poor advice.

BTW, since alloca() doesn't survive function scope, might as well use malloc/free instead of the GC. Or do like I've done and have an array of preallocated larger buffers.

I.e. if you've gotten to tuning code at this level, the compiler picking things automatically for you is unlikely to be helpful. Hence my not being convinced by bearophile's assessment.
April 24, 2015
On Friday, 24 April 2015 at 01:54:11 UTC, Walter Bright wrote:
> On 4/23/2015 3:11 PM, deadalnix wrote:
>> For arbitrary large, you can always do something like :
>>
>> Item* itemPtr = (arbitrarylarge < thresold)
>>   ? alloca(arbitrarylarge)
>>   : GC.alloc(arbitrarylarge);
>>
>> One extra check compared to a heap allocation is not going to make things
>> terrible, and it is likely to be very predictible anyway (most arbitrarylarge
>> size are actually small in practice).
>
> You can, but it just doesn't pay off. Even if you found a case that did, it doesn't mean it pays off in general, and so would be poor advice.
>
> BTW, since alloca() doesn't survive function scope, might as well use malloc/free instead of the GC. Or do like I've done and have an array of preallocated larger buffers.
>
> I.e. if you've gotten to tuning code at this level, the compiler picking things automatically for you is unlikely to be helpful. Hence my not being convinced by bearophile's assessment.

Except of course that alloca is a lot cheaper than malloc/free.