DIP60: @nogc attribute

Manu via Digitalmars-d digitalmars-d at puremagic.com
Fri Apr 18 02:46:25 PDT 2014


On 17 April 2014 18:35, Walter Bright via Digitalmars-d <
digitalmars-d at puremagic.com> wrote:

> On 4/16/2014 8:13 PM, Manu via Digitalmars-d wrote:
>
>> On 17 April 2014 03:37, Walter Bright via Digitalmars-d
>> <digitalmars-d at puremagic.com <mailto:digitalmars-d at puremagic.com>> wrote:
>>     ARC has very serious problems with bloat and performance.
>> This is the first I've heard of it, and I've been going on about it for
>> ages.
>>
>
> Consider two points:
>
> 1. I can't think of any performant ARC systems.
>

Consensus is that there's no performant GC available to D either.
Can you show that Obj-C suffers serious performance penalty from it's ARC
system? Have there been comparisons?


2. Java would be a relatively easy language to implement ARC in. There's
> probably a billion dollars invested in Java's GC. Why not ARC?


Java is designed to be GC compatible from the ground up. D is practically
incompatible with GC in the same way as C, but it was shoe-horned in there
anyway.
Everyone that talks about fantasy 'awesome-GC's admits it would be
impossible to implement in D for various reasons.

I think Rainer's GC is a step forward; precision is definitely valuable,
but benchmarks showed that it was slower. That didn't put anyone off
though. I think it was generally agreed that precision trumped a small
performance impact.


 Obviously, a critical part of ARC is the compilers ability to reduce
>> redundant
>> inc/dec sequences. At which point your 'every time' assertion is false.
>> C++
>> can't do ARC, so it's not comparable.
>>
>
> C++ has shared_ptr, with all kinds of escapes.


That's a library. The compiler knows nothing. Ref counting is useless
without compiler support.


 With proper elimination, transferring ownership results in no cost, only
>> duplication/destruction, and those are moments where I've deliberately
>> committed
>> to creation/destruction of an instance of something, at which point I'm
>> happy to
>> pay for an inc/dec; creation/destruction are rarely high-frequency
>> operations.
>>
>
> inc/dec isn't as cheap as you imply. The dec usually requires the creation
> of an exception handling unwinder to do it.
>

Why do you need to do that?

The thing is, it's potentially 'workable'. It's also easy to rearrange and
factor out of hot code.
It's predictable and well understood.


 Have you measured the impact?
>>
>
> No. I don't really know how I could, as I haven't seen an ARC system.
>

Why do you have such a strong opposition if this is the case?


 I've never heard of Obj-C users complaining about the inc/dec costs.
>>
>
> Obj-C only uses ARC for a minority of the objects.
>

But you're always talking about how D creates way less garbage than other
languages, which seems to be generally true. It needs to be tested before
you can make presumptions about performance.
D offers some unique opportunities to improve on existing ARC
implementations, and combined with D's relative less garbage than other
languages, you might be surprised...


 How often does ref fiddling occur in reality? My guess is that with
>> redundancy
>> elimination, it would be surprisingly rare, and insignificant.
>>
>
> Yes, I would be surprised.
>

Well, I'd like to see it measured in practise. But most common scenarios I
imagine appear like they'd eliminate nicely.
pure, and perhaps proper escape analysis (planned?) offer great opportunity
for better elimination than other implementations like Obj-C.


     Further problems with ARC are inability to mix ARC references with
>> non-ARC
>>     references, seriously hampering generic code.
>> That's why the only workable solution is that all references are ARC
>> references.
>> The obvious complication is reconciling malloc pointers, but I'm sure
>> this can
>> be addressed with some creativity.
>>
>> I imagine it would look something like:
>> By default, pointers are fat: struct ref { void* ptr, ref_t* rc; }
>>
>
> First off, now pointers are 24 bytes in size. Secondly, every pointer
> dereference becomes two dereferences (not so good for cache performance).
>

That's not necessarily true. What length is the compiler typically able to
eliminate inc/dec pairs? How many remain in practise? We don't know.
The performance is to be proven. Under this approach, you'd bunch
references up close together, so there's a higher than usual probability
the rc will be in cache already.
I agree, it's theoretically a problem, but I have no evidence to show that
it's a deal breaker. In lieu of any other options, it's worth exploring.


 malloc pointers could conceivably just have a null entry for 'rc' and
>> therefore
>> interact comfortably with rc pointers.
>> I imagine that a 'raw-pointer' type would be required to refer to a thin
>> pointer. Raw pointers would implicitly cast to fat pointers, and a
>> fat->thin
>> casts may throw if the fat pointer's rc is non-null, or compile error if
>> it can
>> be known at compile time.
>>
>
> Now we throw in a null check and branch for pointer operations.
>

Well the alternative is to distinguish them in the type system. Without
making any language changes, I guess it's a requirement.
It would be completely predictable though, so it only amounts to a couple
of cycles.


 Perhaps a solution is possible where an explicit rc record is not required
>> (such
>> that all pointers remain 'thin' pointers)...
>> A clever hash of the pointer itself can look up the rc?
>> Perhaps the rc can be found at ptr[-1]? But then how do you know if the
>> pointer
>> is rc allocated or not? An unlikely sentinel value at ptr[-1]? Perhaps the
>> virtual memory page can imply whether pointers allocated in that region
>> are ref
>> counted or not? Some clever method of assigning the virtual address space
>> so
>> that recognition of rc memory can amount to testing a couple of bits in
>> pointers?
>>
>> I'm just making things up,
>>
>
> Yes.
>

I'm sure there are plenty of cool/clever tricks that may help.


 but my point is, there are lots of creative
>> possibilities, and I have never seen any work to properly explore the
>> options.
>>
>
> ARC has been known about for many decades. If you haven't seen it
> "properly explored", perhaps it isn't as simple and cost-effective as it
> may appear at first blush.
>

I didn't say it was simple or cost effective. I don't know. I'm asking, is
it *possible* and would it work well?
I want to know why it's not possible, and if it is, then promote
exploration as a potential solution in D.


 So then consider ARC seriously. If it can't work, articulate why. I still
>> don't
>> know, nobody has told me.
>> It works well in other languages, and as far as I can tell, it has the
>> potential
>> to produce acceptable results for _all_ D users.
>>
>
> What other languages?
>

Well, Apple are the obvious demonstration that I'm familiar with. I haven't
worked with any others, but they have been raised by other people in prior
threads.


 iOS is a competent realtime platform, Apple are well known for their
>> commitment
>> to silky-smooth, jitter-free UI and general feel.
>>
>
> A UI is a good use case for ARC. A UI doesn't require high performance.
>

Nothing that requires high-frequency performance is a good case for managed
memory at all. You can't invoke a system allocator no matter how it's
implemented at the sort of frequency I think you're suggesting.
Apple demonstrate that direct application of ARC results in silky smooth
performance. That's hard to do, and it's throughout all user facing API's,
not just UI, so it's clearly not inhibiting that goal substantially.
I've haven't heard iOS programmers complain about it. I have heard Android
programmers complain about the GC extensively though.

Like I say, programmers would quickly learn the patterns (since they are
predictable and reliable), and it appears that D offers substantially more
opportunity for effective ref-fiddling-elimination than Obj-C.

 Okay. Where can I read about that? It doesn't seem to have surfaced, at
>> least,
>> it was never presented in response to my many instances of raising the
>> topic.
>> What are the impasses?
>>
>
> I'd have to go look to find the thread. The impasses were as I pointed out
> here.
>

I don't feel like you pointed any out. Just FUD.


 I'm very worried about this. ARC is the only imaginary solution I have
>> left. In
>> lieu of that, we make a long-term commitment to a total fracturing of
>> memory
>> allocation techniques, just like C++ today where interaction between
>> libraries
>> is always a massive pain in the arse. It's one of the most painful things
>> about
>> C/C++, and perhaps one of the primary causes of incompatibility between
>> libraries and frameworks. This will transfer into D, but it's much worse
>> in D
>> because of the relatively high number of implicit allocations ('~',
>> closures, etc).
>>
>
> There are only about 3 cases of implicit allocation in D, all easily
> avoided, and with @nogc they'll be trivial to avoid. It is not "much worse".
>

But they are fundamentally useful and convenient features though. I don't
want to have to emplace policy to ban them.
It separates a subset of D users as second class citizens that can't enjoy
the modern features of the language, and restricts their access to
libraries.

The thing is, these policies must become system-wide. GC must be banned
everywhere to have any effect. Under a GC, even the low frequency code
loses these conveniences offered by the D language, and you're creating a
situation where libraries become very hard to trust.


 Frameworks and libraries become incompatible with each other, which is a
>> problem
>> in C/C++ that modern languages (java, C#, python, etc) typically don't
>> suffer.
>>
>
> A GC makes libraries compatible with each other, which is one reason why
> GCs are very popular.
>

Correct, and ARC as a form of GC would equally be applicable everywhere.
That's my point. By sticking with a crappy GC, you're isolating an
(important?) subset of D users into a world where we suffer annoying C++
patterns yet longer, and still can't depend on interoperability with useful
libraries. These are critical failings of C++ by my measure. And
foundational to my attraction to D in the first place.

I don't feel like you've given me any evidence that ARC in not feasible.
Just that you're not interested in trying it out.
Please, kill it technically. Not just with dismissal and FUD.


I fear that @nogc is a sort of commitment to the notion that the GC is here
to stay, will never be improved or changed, and that we are being boxed
into a world no different from C++. I'm not here because I want C++ with
better syntax, I'm here because I want to encourage the language that best
embodies the future of my industry.
I've put decades into manual memory management. I'm tired of it. So are all
the other game devs. Demonstrably so - many of whom are toying with C# and
other languages; which may be compatible with modern casual games, but not
compatible with major titles, or console/embedded titles. Nobody wants to
work with C++ anymore.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20140418/48be3c01/attachment-0001.html>


More information about the Digitalmars-d mailing list