October 25, 2013
On Friday, 25 October 2013 at 11:21:55 UTC, Jakob Ovrum wrote:
> On Friday, 25 October 2013 at 10:02:08 UTC, Namespace wrote:
>> On Friday, 25 October 2013 at 09:51:40 UTC, Maxim Fomin wrote:
>>> On Friday, 25 October 2013 at 09:37:23 UTC, Namespace wrote:
>>>>
>>>> We would have then the possibility to manage our memory by ourself. One of D's promises is, that the GC can be disabled. Yes, it can, but then we have many many things which do not work. For example built-in arrays.
>>>
>>> Not only arrays, but classes, throwables, scope exits, new operator, nested structs, etc.
>>
>> Thats right.
>> But I often use temporary arrays, but I still don't like them because they are always consume so much GC memory. But with allocators that would end.
>> Let us hope that Walter has the right intention and that Andrei design the allocators for this purpose.
>
> Why does it have to be the opaque druntime dynamic array? Why can't you use the hypothetical (planned, rather) std.container.Array that supports custom allocators, or a type of your own design?

Because Array!int looks a lot more ugly than such a nice thing as int[]. And if it is possible to change the allocator for some arrays, why shouldn't we implement it?
The default allocator would stay the GC allocator. So if you don't want to swap the allocator of your arrays, don't do it.
October 25, 2013
On 10/24/2013 09:54 PM, Andrei Alexandrescu wrote:
> Hello,
>
>
> I know it's been a long wait. Hopefully it was worth it. The alpha release of untyped allocators is ready for tire-kicking and a test drive.
>
> Code: https://github.com/andralex/phobos/blob/allocator/std/allocator.d
>
> Dox: http://erdani.com/d/phobos-prerelease/std_allocator.html

Looks good.

> ...
>
> Please destroy! I've literally sweat as I'm sending this :o).
>...

- Possible null dereference on line 3128. :o)
  (In general, CascadingAllocator is not yet very composable. It should return null allocations instead of failing in undocumented ways. It should probably also allow the 'make' function to return null.)

- "CAllocator". The name is non-descriptive/misleading.

- Preconditions should be in the corresponding section.
October 25, 2013
On 2013-10-25 02:01, Andrei Alexandrescu wrote:

> Oddly enough this can be actually done.
>
> with (setAllocator!Mallocator)
> {
>     ...
> }
>
> setAllcator returns an rvalue that changes the global allocator to the
> Mallocator in the constructor, and restores it to whatever it was in the
> destructor.

Wouldn't this be very unsafe? Say you call another function inside the with-statement and that function assumes the standard GC for allocating memory.

-- 
/Jacob Carlborg
October 25, 2013
> Please destroy! I've literally sweat as I'm sending this :o).

This looks fantastic. Congratulations!

October 25, 2013
On Friday, 25 October 2013 at 12:07:30 UTC, Namespace wrote:
> On Friday, 25 October 2013 at 11:21:55 UTC, Jakob Ovrum wrote:
>> On Friday, 25 October 2013 at 10:02:08 UTC, Namespace wrote:
>>> On Friday, 25 October 2013 at 09:51:40 UTC, Maxim Fomin wrote:
>>>> On Friday, 25 October 2013 at 09:37:23 UTC, Namespace wrote:
>>>>>
>>>>> We would have then the possibility to manage our memory by ourself. One of D's promises is, that the GC can be disabled. Yes, it can, but then we have many many things which do not work. For example built-in arrays.
>>>>
>>>> Not only arrays, but classes, throwables, scope exits, new operator, nested structs, etc.
>>>
>>> Thats right.
>>> But I often use temporary arrays, but I still don't like them because they are always consume so much GC memory. But with allocators that would end.
>>> Let us hope that Walter has the right intention and that Andrei design the allocators for this purpose.
>>
>> Why does it have to be the opaque druntime dynamic array? Why can't you use the hypothetical (planned, rather) std.container.Array that supports custom allocators, or a type of your own design?
>
> Because Array!int looks a lot more ugly than such a nice thing as int[].

If the template syntax is too ugly then we've really failed at designing an extensible development platform. Even so, with type inference and aliases, the need to write down involved names is all but eliminated (not that I think Array!int is a particularly involved name).

Not everything belongs in the core language. Conflating slices with garbage collected dynamic arrays is a mistake we have to live with, but let's not make the situation even more complicated.

> And if it is possible to change the allocator for some arrays, why shouldn't we implement it?

Because it has a significant cost.

> The default allocator would stay the GC allocator. So if you don't want to swap the allocator of your arrays, don't do it.

That's fine as long as you only use the array locally and don't pass it to any code that depends on infinite lifetime semantics. It also enables circumvention of SafeD unless some language rules are changed.
October 25, 2013
On Friday, 25 October 2013 at 14:09:55 UTC, Jakob Ovrum wrote:
> On Friday, 25 October 2013 at 12:07:30 UTC, Namespace wrote:
>> On Friday, 25 October 2013 at 11:21:55 UTC, Jakob Ovrum wrote:
>>> On Friday, 25 October 2013 at 10:02:08 UTC, Namespace wrote:
>>>> On Friday, 25 October 2013 at 09:51:40 UTC, Maxim Fomin wrote:
>>>>> On Friday, 25 October 2013 at 09:37:23 UTC, Namespace wrote:
>>>>>>
>>>>>> We would have then the possibility to manage our memory by ourself. One of D's promises is, that the GC can be disabled. Yes, it can, but then we have many many things which do not work. For example built-in arrays.
>>>>>
>>>>> Not only arrays, but classes, throwables, scope exits, new operator, nested structs, etc.
>>>>
>>>> Thats right.
>>>> But I often use temporary arrays, but I still don't like them because they are always consume so much GC memory. But with allocators that would end.
>>>> Let us hope that Walter has the right intention and that Andrei design the allocators for this purpose.
>>>
>>> Why does it have to be the opaque druntime dynamic array? Why can't you use the hypothetical (planned, rather) std.container.Array that supports custom allocators, or a type of your own design?
>>
>> Because Array!int looks a lot more ugly than such a nice thing as int[].
>
> If the template syntax is too ugly then we've really failed at designing an extensible development platform. Even so, with type inference and aliases, the need to write down involved names is all but eliminated (not that I think Array!int is a particularly involved name).
>
> Not everything belongs in the core language. Conflating slices with garbage collected dynamic arrays is a mistake we have to live with, but let's not make the situation even more complicated.
I don't get your problem.

>> And if it is possible to change the allocator for some arrays, why shouldn't we implement it?
>
> Because it has a significant cost.
Which cost?

>
>> The default allocator would stay the GC allocator. So if you don't want to swap the allocator of your arrays, don't do it.
>
> That's fine as long as you only use the array locally and don't pass it to any code that depends on infinite lifetime semantics. It also enables circumvention of SafeD unless some language rules are changed.
The language cannot protect you from every mistake you can do. You should know what you do. If you don't, don't use such a feature. It's very simple.
October 25, 2013
On 25 October 2013 05:54, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org
> wrote:

> Hello,
>
>
> I know it's been a long wait. Hopefully it was worth it. The alpha release of untyped allocators is ready for tire-kicking and a test drive.
>
> Code: https://github.com/andralex/**phobos/blob/allocator/std/** allocator.d<https://github.com/andralex/phobos/blob/allocator/std/allocator.d>
>
> Dox: http://erdani.com/d/phobos-**prerelease/std_allocator.html<http://erdani.com/d/phobos-prerelease/std_allocator.html>
>
> Warning: this is alpha quality. Unit tests are thin, and there are no benchmarks. Both would be appreciated, particularly benchmarks to validate the gains (which I speculate can be very sizable) of custom-built, special-purpose allocators compared to traditional allocators.
>
> I acknowledge I'm clearly in no position to evaluate this design. I have been knocking around it for long enough to have no idea how easy it is to get into it from the outside, or how good it is. By all signs I could gather this feels like good design, and one of the best I've ever put together. The allocators defined have an archetypal feeling, are flexible both statically and dynamically, and morph and combine in infinite ways.
>
> CAllocator and CAllocatorImpl make the link between the static and dynamic worlds. Once an allocator is assembled out of pieces and finely tuned, wrapping it in a dynamic API is a snap.
>
> Please destroy! I've literally sweat as I'm sending this :o).


I like it. It seems like a solid foundation.
I'm still very curious to see how the next phase (deep language
integration) will look though.


My immediate reactions:

1. I'm still sad there are no allocAligned() functions or something of that
type to request explicit alignment with allocations. I'm not sure there is
sufficient support for requesting alignment with allocations. The set-able
alignment property approach seems a little weird (and only seemed to be
supported on one allocator?). I guess experience will tell if this is
sufficient and/or convenient.
I'd still like to see an allocWithAlignment() method or something, which
may be implemented efficiently by allocators that can support it.

2. I see some lines like this:
 assert(parent.alignment >= X.alignof);
What if parent.alignment < X.alignof? If 'parent' is something with an
inflexible alignment, like malloc or the GC, what is the proper
(convenient) way to reconcile the requirement?

3. FreeList has some options; minSize, maxSize, maxNodes. When I'm using a freelist, the most important option to me is to be able to allocate new nodes in batches. I'd like an option added to control the batch size, so multiple new nodes are allocated in contiguous blocks when the pool grows. Perhaps add a 4th parameter; minBatchSize = 1? (to retain support for your existing logic batching small allocations into larger allocated blocks) The main reasons for this are cache/spatial locality of small allocations, and minimising overhead burden on the upstream allocator.

4. OT: Working with D struct's, you often encounter, for instance:

struct Region(uint minAlign = platformAlignment)
{
private BasicRegion!(minAlign) base;
...

Doesn't this make you sad? It makes me sad quite regularly. Especially when the very next line is (often): alias base this;


October 25, 2013
On 10/25/13 1:21 AM, simendsjo wrote:
> On Thursday, 24 October 2013 at 19:53:56 UTC, Andrei Alexandrescu wrote:
>> Hello,
>>
>>
>> I know it's been a long wait. Hopefully it was worth it. The alpha
>> release of untyped allocators is ready for tire-kicking and a test drive.
>
> Does anyone has good resources on allocators in general? I've mostly
> used malloc/free and GCs. None of the books I've read has gone into
> allocators..

I don't know of any literature in book format. There are a few papers though on HeapLayers, Hoard, jemalloc, and probably more. Fetch a couple and see what they cite and who cites them.

Andrei

October 25, 2013
On 10/25/13 5:07 AM, Namespace wrote:
> On Friday, 25 October 2013 at 11:21:55 UTC, Jakob Ovrum wrote:
>> On Friday, 25 October 2013 at 10:02:08 UTC, Namespace wrote:
>>> On Friday, 25 October 2013 at 09:51:40 UTC, Maxim Fomin wrote:
>>>> On Friday, 25 October 2013 at 09:37:23 UTC, Namespace wrote:
>>>>>
>>>>> We would have then the possibility to manage our memory by ourself.
>>>>> One of D's promises is, that the GC can be disabled. Yes, it can,
>>>>> but then we have many many things which do not work. For example
>>>>> built-in arrays.
>>>>
>>>> Not only arrays, but classes, throwables, scope exits, new operator,
>>>> nested structs, etc.
>>>
>>> Thats right.
>>> But I often use temporary arrays, but I still don't like them because
>>> they are always consume so much GC memory. But with allocators that
>>> would end.
>>> Let us hope that Walter has the right intention and that Andrei
>>> design the allocators for this purpose.
>>
>> Why does it have to be the opaque druntime dynamic array? Why can't
>> you use the hypothetical (planned, rather) std.container.Array that
>> supports custom allocators, or a type of your own design?
>
> Because Array!int looks a lot more ugly than such a nice thing as int[].
> And if it is possible to change the allocator for some arrays, why
> shouldn't we implement it?
> The default allocator would stay the GC allocator. So if you don't want
> to swap the allocator of your arrays, don't do it.

Maintaining per-array-object allocators could be quite expensive. Two other possibilities are keeping one allocators for all array of a given type and of course keeping a global allocator for all arrays.

Andrei

October 25, 2013
On Friday, 25 October 2013 at 00:00:36 UTC, Andrei Alexandrescu wrote:
> with (setAllocator!Mallocator)

That'd be a mistake except perhaps in two circumstances:

1) if setAllocator was @system with warnings attached.

or

2) if the content inside the with block was all a pure function.

#1 is obvious, storing a reference to freed memory isn't @safe nor pretty. But I think #2 is somewhat interesting. A pure function cannot escape any reference, since it isn't allowed to access outside mutable data at all. When the pure function returns, the only possible places one of the other allocated values could be are in one of its parameters - which are set right here on the same (or the immediately following) line as the call to setAllocator, so it is no surprise, or the return value, and ditto.

Otherwise, by the pure rules, they must all be local and thus freeing them is fine.


I'm not quite sold on replacing the global allocator. I'd generally prefer to use a container type so it is clear who the owner is, and then if anything, just prohibit slice concat (and preferably, storing them too, scope storage class!!!!111!one) so you don't accidentally reallocate without informing the owner.

But if we did do it, signatures like

@system AllocatorResetStruct setAllocator(Allocator)() {}

and

@safe void setAllocator(Allocator)(pure @safe void function() code) {}

just might work out.