On Sun, 21 Nov 2010 17:54:25 -0500, Johann MacDonagh
<johann.macdonagh....@spam..gmail.com> wrote:
On 11/16/2010 12:58 PM, bearophile wrote:
Steven Schveighoffer:
The experienced programmers may write "scope int[] a...", and have no
heap allocations.
This is a good idea. This isn't what I thought spir was saying, I
thought
he wanted the function to always allocate.
I have also suggested that when "scope" is not present, DMD may
automatically add a runtime test similar to the one done by
ensureHeaped and dup the array data only if it's on the stack. So even
when you don't use "scope" it doesn't always copy.
The only issue I see here is that scope should really be the default,
because that is what you want most of the time.
If the variadics is in the signature of a free function then I agree
with you. But if it's inside the this() of a class, then often you want
that data on the heap.
However, the compiler
cannot prove that the data doesn't escape so it can't really enforce
that
as the default.
If you look at my original answer I have suggested something like
@heaped, that's attached to an array and makes sure its data is on the
heap. This is done with a mix (when possible) of static analysis and
runtime tests (in the other cases). But I have not added this idea to
the enhancement request of scoped variadics because it looks too much
hard to implement in D/DMD.
I believe the compiler cannot really be made to enforce that all
passed-in
data will be heap-allocated when passed to foo. A runtime check would
be
a very good safety net.
Static analysis is able to do this and more, but it requires some logic
added to the compiler (and such logic probably doesn't work in all
cases).
I have even suggested a transitive @noheap annotation, similar to
@nothrow, that makes sure a function contains no heap allocations and
doesn't call other things that perform heap allocations:
http://d.puremagic.com/issues/show_bug.cgi?id=5219
The proliferation of function attributes produces "interesting"
results:
@noheap @safe nothrow pure real sin(in real x) { ... }
This is a bit much. Introducing these attributes is viral -- once you
go
@noheap, anything you call must be @noheap, and the majority of
functions
will need to be marked @noheap. The gain is marginal at best anyways.
Indeed, it's a lot, and I am not sure it's a good idea.
I have had this idea reading one or two articles written by people that
write high performance games in C++. They need to keep the frame rate
constantly higher than a minimum, like 30/s or 60/s. To do this they
have to avoid C heap allocations inside certain large loops (D GC heap
allocations may be even worse). Using @noheap is a burden, but it may
help you write code with a more deterministic performance.
Maybe someday it will be possible to implement @noheap with
user-defined attributes plus static reflection, in D. But then the
standard library will not use that user-defined @noheap attribute,
making it not so useful. So if you want it to be transitive, Phobos
needs to be aware of it.
Bye,
bearophile
I'm for the "safe by default, you have to work to be unsafe". In this
case, the compiler should have noticed the data was being escaped and
passed 1,2,3 as a heap (or perhaps auto-duped at the point it was
assigned). It does this kind of thing when you have a closure (nested
delegate).
The variadic syntax is confusing (although arguably probably the best
way to deal with it). An average developer expects assignments to always
be safe. Assigning a function scope static array to a global static or
dynamic array results in either copying or a heap allocation / copying.
There's no need to "think about it" as you would in C. You simply assign
and it works.
Although I do agree some kind of compiler switch that tells you when
there hidden heap allocations would be nice for performance tuning.
Let's say you give the compiler this .di file:
void foo(int[] nums...);
And an object file, how does the compiler know whether nums escapes or not?
The answer is, it cannot. That is the problem with D's compilation model
which makes analysis impossible. One must declare the intentions first
(via the function signature), and then adhere to the intentions.
Bearophile's idea of using scope is good, we can probably make that work.
-Steve