Designing with the GC out of mind

JS js.mdnq at gmail.com
Tue Aug 6 06:43:00 PDT 2013


On Tuesday, 6 August 2013 at 12:41:26 UTC, Adam D. Ruppe wrote:
> On Tuesday, 6 August 2013 at 07:19:40 UTC, JS wrote:
>> 1. Is there a way to determine what the GC is doing?
>
> It is probably easiest to just run it in a debugger, and set a 
> breakpoint on gc_malloc and gc_qalloc. When it breaks, you can 
> see where it is, then continue to carry on.
>
> You can also tell where the gc runs by carefully reviewing the 
> code:
>
> 1) any instance of "new", obviously
>
> 2) any use of array ~ array. Binary ~ on other types doesn't 
> necessarily run the gc, since it could be overloaded, but 
> generally does. (If you want to avoid gc, a ~ b is something 
> I'd avoid entirely.)
>
> 3) Some uses of a ~= b. This doesn't necessarily allocate, it 
> might be appending to reserved space or be overloaded. If a is 
> a built in array though and you're looking at the code, assume 
> it allocates and do something else.
>
> 4) Passing a nested delegate or lambda to another function, 
> sometimes. It won't if a) the receiving function marks the 
> delegate argument as scope, or b) the function doesn't 
> reference any variables.
>
> But generally if you see a non-scope delegate, assume it 
> allocates.
>
> 5) Any array literal that isn't static immutable allocates. 
> Hopefully this will be fixed soon, but right now they all do... 
> even if the array literal is in an enum!
>
> ummm... I think I might be forgetting something, but I'm pretty 
> sure these are all the major ones.
>
> Anything that allocates might call the gc collect.
>
>
> So to sum up: search your code for "new", "~", calling 
> functions that receive "delegate", and "[a,b,c...]" and you'll 
> have an idea as to where the gc might run in your code.
>

Thanks. It looks like the bulk can be avoided except by writing 
custom arrays types.

I'd still like some easy way to hook into the GC to monitor what 
is going on though because ultimately I'd like to disable the GC 
but then must guarantee that memory is not leaking.

>> I suppose I can modify the sources, but is there an easier way?
>
> What about writing your own external alloc function like 
> std.conv.emplace? Then you'd do it just at the creation site 
> without modifying the class.

Well, I am using an interface to allow for various strategies 
that can also change dynamically. e.g..,

interface iNew(T) { final static T New(Args...)(Strategy, Args 
args) { .. } }

all of my objects will inherit this interface.  The only issue is 
that they must do so, I see no need to have to manually add the 
inheritance. I also worry about size allocation but it seems the 
typeid you mention should solve this(but to be honest, I don't 
know if it will completely solve the issue or how performant it 
is). There is TypeInfo, but again, I don't know how performant. 
By having every object implement a Size and return it's size wold 
work fine though.

e.g.,

interface iNew(T)
{
     @property size_t Size();
     final static T New(Args...)(Strategy, Args args) { .. }
}

But it would be nice if Size was automatically implemented in 
each class(since all it does is return a constant). The overhead 
is just a function call rather than some reflection type of 
stuff. Having iNew implicitly inherited and Size() implicitly 
generated is what I'm after. I'll check out the alternative 
Size() methods and see if they are satisfactory.



More information about the Digitalmars-d mailing list