On Phobos GC hunt
Dmitry Olshansky via Digitalmars-d
digitalmars-d at puremagic.com
Wed Oct 8 05:08:59 PDT 2014
On Wednesday, 8 October 2014 at 11:25:25 UTC, Johannes Pfau wrote:
> Am Tue, 07 Oct 2014 15:57:58 +0000
> schrieb "Dmitry Olshansky" <dmitry.olsh at gmail.com>:
>
>>
>> Instead we need to observe patterns and label it automatically
>> until the non-trivial subset remains. So everybody, please
>> take time and identify simple patterns and post back your
>> ideas on solution(s).
>>
>
> I just had a look at all closure allocations and identified
> these
> patterns:
Awesome! This is exactly the kind of help I wanted.
>
>
> 1) Fixable by manually stack-allocating closure
> A delegate is passed to some function which stores this
> delegate and
> therefore correctly doesn't mark the parameter as scope.
> However,
> the lifetime of the stored delegate is still limited to the
> current
> function (e.g. it's stored in a struct instance, but on the
> stack).
>
> Can be fixed by creating a static struct{T... members; void
> doSomething(){access members}} instance on stack and passing
> &stackvar.doSomething as delegate.
Hm... Probably we can create a template for this.
>
> 2) Using delegates to add state to ranges
> ----
> return iota(dim).
> filter!(i => ptr[i])().
> map!(i => BitsSet!size_t(ptr[i], i * bitsPerSizeT))().
> joiner();
> ----
> This code adds state to ranges without declaring a new type:
> the ptr
> variable is not accessible and needs to be move into a
> closure.
> Declaring a custom range type is a solution, but not
> straightforward: If the ptr field is moved into the range a
> closure
> is not necessary. But if the range is copied, it's address
> changes
> and the delegate passed to map is now invalid.
>
Indeed, such code is fine in "user-space" but have no place in
the library.
> 3) Functions taking delegates as generic parameters
> receiveTimeout,receive,formattedWrite accept different types,
> including delegates. The delegates can all be scope to avoid
> the
> allocation but is void foo(T)(scope T) a good idea? The
> alternative
> is probably making an overload for delegates with scope
> attribute.
>
> (The result is that all functions calling receiveTimeout,...
> with a
> delegate allocate a closure)
>
> 4) Solvable with manual memory management
> Some specific functions can't be easily fixed, but the
> delegates
> they create have a well defined lifetime (for example spawn
> creates
> a delegate which is only needed at the startup of a new
> thread, it's
> never used again). These could be malloc+freed.
>
I think this and (2) can be solved if we come up with solid
support for RC-closures.
> 5) Design issue
> These functions generally create a delegate using variables
> passed
> in as parameters. There's no way to avoid closures here.
> Although
> manual allocation is an possible, the lifetime is undefined
> and can
> only be managed by the GC.
>
> 6) Other
> Two cases can be fixed by moving a buffer into a struct or
> moving a
> function out of a member function into it's surrounding
> class.
>
Yeah, there are always outliers ;)
> Also notable: 17 out of 35 cases are in std.net.curl. This is
> because
> curl heavily uses delegates and wrapper delegates.
Interesting... it must be due to cURL callback-based API.
All in all, std.net.curl is a constant source of complaints, it
may need some work to fix other issues anyway.
More information about the Digitalmars-d
mailing list