December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Sunday, 8 December 2013 at 00:17:48 UTC, Adam D. Ruppe wrote:
> On Sunday, 8 December 2013 at 00:16:46 UTC, Adam D. Ruppe wrote:
>> the same general pattern there of static array up to a certain size.
>
> static array being "T[max_size]", not "static T[max_size]"
>
> just so it uses the stack for most things.
So rather something like this:
----
import std.stdio;
struct Helper(T, uint StackSize = 128) {
T[StackSize] buffer = void;
T[] allocate(size_t n) {
if (n <= StackSize)
return buffer[0 .. n];
return new T[n];
}
}
void main() {
auto h = Helper!int();
int[] arr = h.allocate(512);
}
----
Yes? I don't like it, because it isn't a one liner. Isn't it possible in one line?
A personal dream of me would be: scope int[] arr = new int[n]; or the implementation of DIP46. :)
|
December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | On Sunday, 8 December 2013 at 09:14:44 UTC, Dmitry Olshansky wrote:
> 08-Dec-2013 02:32, Namespace пишет:
>> Since my last thread doesn't get much attention I like to ask here: How
>> did you deal with temporary memory? Let's assume that the size is only
>> known at runtime.
>> I have this situation e.g. in Dgame in the capture method: I get the
>> pixel data from my Window with glReadPixel but it is reversed. So I have
>> to reverse it again, but I still need at least temporary memory for one
>> pixel-line which stores the currently swapped pixels. So how would you
>> solve such a situation?
>>
>> Since D doesn't offer VLA's and alloca is broken (besides the ugly syntax),
>> I use a scoped wrapper (since scope doesn't do the job):
>>
>> ----
>> struct scoped(A : T[], T) {
>> T[] arr;
>>
>> alias arr this;
>>
>> this(T[] arr) {
>> this.arr = arr;
>>
>> writefln("Get %d %s's (ptr = %x)", arr.length, T.stringof,
>> arr.ptr);
>> }
>>
>> ~this() {
>> GC.free(this.arr.ptr);
>> this.arr = null;
>> GC.minimize();
>
> This is slow. Just use malloc & free, why touch GC at all?
>> }
>> }
>>
>> void main() {
>> // need temp memory
>> scoped!(int[]) arr = new int[n];
>> }
>> ----
>>
>> And what do you use?
Because it's more D'ish. That is what D offers.
Why is it slower than malloc + free?
|
December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Sunday, 8 December 2013 at 09:25:41 UTC, Namespace wrote:
> On Sunday, 8 December 2013 at 09:14:44 UTC, Dmitry Olshansky wrote:
>> 08-Dec-2013 02:32, Namespace пишет:
>>> Since my last thread doesn't get much attention I like to ask here: How
>>> did you deal with temporary memory? Let's assume that the size is only
>>> known at runtime.
>>> I have this situation e.g. in Dgame in the capture method: I get the
>>> pixel data from my Window with glReadPixel but it is reversed. So I have
>>> to reverse it again, but I still need at least temporary memory for one
>>> pixel-line which stores the currently swapped pixels. So how would you
>>> solve such a situation?
>>>
>>> Since D doesn't offer VLA's and alloca is broken (besides the ugly syntax),
>>> I use a scoped wrapper (since scope doesn't do the job):
>>>
>>> ----
>>> struct scoped(A : T[], T) {
>>> T[] arr;
>>>
>>> alias arr this;
>>>
>>> this(T[] arr) {
>>> this.arr = arr;
>>>
>>> writefln("Get %d %s's (ptr = %x)", arr.length, T.stringof,
>>> arr.ptr);
>>> }
>>>
>>> ~this() {
>>> GC.free(this.arr.ptr);
>>> this.arr = null;
>>> GC.minimize();
>>
>> This is slow. Just use malloc & free, why touch GC at all?
>>> }
>>> }
>>>
>>> void main() {
>>> // need temp memory
>>> scoped!(int[]) arr = new int[n];
>>> }
>>> ----
>>>
>>> And what do you use?
>
> Because it's more D'ish. That is what D offers.
> Why is it slower than malloc + free?
Well, for a start you're calling GC.minimize every time you leave the scope, which is an expensive call.
Just using new and GC.free would be fine, but there is really no need to burden the GC with this at all; it's a textbook case for C's malloc/free.
|
December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | 08-Dec-2013 13:25, Namespace пишет: > On Sunday, 8 December 2013 at 09:14:44 UTC, Dmitry Olshansky wrote: >> 08-Dec-2013 02:32, Namespace пишет: [snip] >>> >>> And what do you use? > > Because it's more D'ish. There is no such objective quality as being D'ish. GC.malloc/GC.free are no better then malloc/free in code style, readability or observable effect. > That is what D offers. D offers you C run-time as well. In fact it builds on top of it. See also (hopefully) soon to be formally reviewed std.allocator. > Why is it slower than malloc + free? 1. Because GC.minimize does a hell of a work to optimize the whole GC heap. For starters it does collection so as to get rid of floating garbage (AFAIK). 2. You have a trivial use case of deterministic allocation - you know precisely when to deallocate a block. In this setting putting allocated block into tracing GC heap is a waste of time should a collection happen. -- Dmitry Olshansky |
December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | On 12/8/13 4:29 AM, Dmitry Olshansky wrote:
> 08-Dec-2013 13:25, Namespace пишет:
>> On Sunday, 8 December 2013 at 09:14:44 UTC, Dmitry Olshansky wrote:
>>> 08-Dec-2013 02:32, Namespace пишет:
> [snip]
>>>>
>>>> And what do you use?
>>
>> Because it's more D'ish.
>
> There is no such objective quality as being D'ish.
> GC.malloc/GC.free are no better then malloc/free in code style,
> readability or observable effect.
If you put (arguably by mistake) a scoped member inside a class, the malloc'd memory will leak but the GC-allocated memory will be ultimately collected.
Andrei
|
December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Saturday, 7 December 2013 at 22:32:59 UTC, Namespace wrote:
> Since my last thread doesn't get much attention I like to ask here: How did you deal with temporary memory?
I just use
scope(exit) delete buf;
Your solution seems to do a GC every time some buffer goes out of scope, which is slooow.
|
December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to thedeemon | On 08/12/13 19:18, thedeemon wrote:
> I just use
> scope(exit) delete buf;
Deprecated or at least disapproved of, no?
|
December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | On Sunday, 8 December 2013 at 18:33:39 UTC, Joseph Rushton Wakeling wrote:
> On 08/12/13 19:18, thedeemon wrote:
>> I just use
>> scope(exit) delete buf;
>
> Deprecated or at least disapproved of, no?
Sadly yes.
|
December 08, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to thedeemon | > I just use
> scope(exit) delete buf;
>
> Your solution seems to do a GC every time some buffer goes out of scope, which is slooow.
I don't need scoped allocations that often. Otherwise I wouldn't use GC.minimize ;) or wouldn't use the GC at all.
John Colvin:
> Well, for a start you're calling GC.minimize every time you leave
> the scope, which is an expensive call.
That was my own decision and is of course not required, but I like to clean up the wasted space. [1]
And as I said, I don't use scope allocations that often.
> Just using new and GC.free would be fine, but there is really no
> need to burden the GC with this at all; it's a textbook case for
> C's malloc/free.
The GC relies also on malloc / free.
Dmitry Olshansky:
> There is no such objective quality as being D'ish.
> GC.malloc/GC.free are no better then malloc/free in code style,
> readability or observable effect.
But I don't use GC.malloc / GC.free. I use new which is IMO a lot nicer and more clean. Of course I now that new is only D syntax for malloc but it is still more clean.
> D offers you C run-time as well. In fact it builds on top of it.
> See also (hopefully) soon to be formally reviewed std.allocator.
It is still C even if D offers the access to the C standard lib.
> 1. Because GC.minimize does a hell of a work to optimize the whole GC
> heap. For starters it does collection so as to get rid of floating
> garbage (AFAIK).
See [1]
|
December 09, 2013 Re: How do you deal with scoped allocations? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Sunday, 8 December 2013 at 19:00:29 UTC, Namespace wrote:
> > Just using new and GC.free would be fine, but there is really no
> > need to burden the GC with this at all; it's a textbook case for
> > C's malloc/free.
> The GC relies also on malloc / free.
Yes, it does. However, obviously it does a lot more than just call malloc/free.
If you statically know the lifetime of a chunk of memory, then there really is no point invoking all that extra heavyweight code* when you can just DIY at no extra cost.**
*and adding to the collection burden (if triggered while the memory is in scope)
**However, take care with unique pointers from inside the allocated block to resources outside the block, as the GC might not be able to find them later (see P.S.).
P.S. does anyone know how the GC interacts with core.stdc.free? I.e. if you free a pointer, but don't null the pointer, presumably the GC will still scan the memory despite it being freed. Isn't this undefined behaviour?
|
Copyright © 1999-2021 by the D Language Foundation