@gc attribute for bypassign @nogc

bitwise via Digitalmars-d digitalmars-d at puremagic.com
Thu Jul 28 08:24:10 PDT 2016


On Thursday, 28 July 2016 at 07:12:06 UTC, Lodovico Giaretta 
wrote:
> On Thursday, 28 July 2016 at 00:23:57 UTC, bitwise wrote:
>> The point is though, that I WANT to use the GC. I want the 
>> memory cleaned up for me, and I don't mind little pauses once 
>> in a while. I just don't want careless allocations to happen 
>> in certain performance-sensitive contexts, like per-frame 
>> updates.
>>
>> While working on a past project(C++), I found this little gem:
>>
>> void draw() {
>>     Font* f = new Font("arial.ttf", 16);
>>     drawText(f, "hello world");
>> }
>>
>> As utterly moronic as this seems, this was a real bug that I 
>> had to fix. Our game was literally topping out at 2GB of 
>> memory usage after ~30 seconds and crashing.
>>
>> Note: it wasn't my code ;)
>>
>> If that code was written in D with the feature I'm asking for, 
>> draw() would have been marked with @nogc. The person who wrote 
>> the above code would have either had to store the font 
>> somewhere else, or insert a @assumenogc{}  section to actually 
>> do that. So it either would not have happened, or would have 
>> been much easier to find.
>>
>> If you found that your game/app was using too much GC, 
>> searching for "@assumenogc" would likely uncover the cause, as 
>> long as your root classes were annotated correctly. The 
>> @assumenogc annotation would plainly show where allocations 
>> were happening that maybe shouldn't be.
>
> If @assumegc has to be manually checked to see if it is 
> over-allocating whenever the application is going out of 
> memory, then it is no more useful than running the gc-profiler 
> when the application is over-allocating. The profiler is even 
> better, because with @assumegc you have to check ALL marked 
> functions to find the leaking one, while the gc-profiler would 
> just put it on top of the report, making your job easier. So 
> IMHO we already have an instrument to solve these problems.

It's not about running out of memory. It's a performance issue.

Example: In the following class, it would be perfectly fine, and 
even expected to allocate in start() but not in update(). This is 
because start() gets called once on object initialization, but 
update() would get called every frame.

class NPC {
     // ....
     void start() { this.hat = new Hat(); }
     void update() @nogc {
         this.timer += Clock.currTime;
         check(this.timer);
         updateUI();
     }
}

Finally, the use of a profiler, and @nogc/@assumenogc wouldn't be 
mutually exclusive. If a profiler had a filter-by-attribute 
functionality, you could set it to @nogc functions, and it would 
narrow down the results to the functions where allocations 
actually matter.

     Bit




More information about the Digitalmars-d mailing list