March 06, 2012
On 6 March 2012 15:10, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 03/06/2012 01:27 PM, Manu wrote:
>
>> concatenation, etc performs bucket loads of implicit GC allocations
>>
>
> a~b
>
> Nothing implicit about that.
>

That is the very definition of an implicit allocation. What about the
concatenation operator says that an allocation is to be expected?
And what if you do a sequence of concatenations: a ~ b ~ c, now I've even
created a redundant intermediate allocation. Will it be cleaned up
immediately?
Is there a convenient syntax to concatenate into a target buffer
(subverting the implicit allocation)? If the syntax isn't equally
convenient, nobody will use it.

This is my single biggest fear in D. I have explicit control within my
>> own code, but I wonder if many D libraries will be sloppy and over-allocate all over the place, and be generally unusable in many applications.
>>
>
> IMHO this fear is unjustified. If the library developers are that sloppy, chances are that the library is not worth using, even when leaving all memory allocation concerns away. (It is likely that you aren't the only programmer familiar with some of the issues.)


I don't think it is unjustified, this seems to be the rule in C/C++ rather
than the exception, and there's nothing in D to suggest this will be
mitigated, possibly worsened...
Many libraries which are perfectly usable in any old 'app' are not usable
in a realtime or embedded apps purely due to its internal design/allocation
habits.
Hopefully the D library authors will be more receptive to criticism... but
I doubt it. I think it'll be exactly as it is in C/C++ currently.



>    Consider C strings. You need to keep track of ownership of it. That
>>    often means creating extra copies, rather than sharing a single copy.
>>
>>
>> Rubbish, strings are almost always either refcounted
>>
>
> Technically, refcounting is a form of GC.


Not really, it doesn't lock up the app at a random time for an indeterminate amount of time.


or on the stack for
>> dynamic strings, or have fixed memory allocated within structures. I don't think I've ever seen someone duplicating strings into separate allocations liberally.
>>
>
> It is impossible to slice a zero-terminated string without copying it in the general case and refcounting slices is not trivial.
>

This is when stack buffers are most common in C.

Who actually uses shared_ptr? Talking about the stl is misleading... an
>>
>> overwhelming number of C/C++ programmers avoid the stl like the plague (for these exact reasons). Performance oriented programmers rarely use STL out of the box, and that's what we're talking about here right?
>>
>
> Possibly now you are the one who is to provide supporting statistics.


Touche :)


If you're not performance oriented, then who cares about the GC either?
>>
>
> There is a difference between not performance oriented and performance agnostic. Probably everyone cares about performance to some extent.
>

True.


On 6 March 2012 15:13, Dmitry Olshansky <dmitry.olsh@gmail.com> wrote:

> On 06.03.2012 16:27, Manu wrote:
>
>>   Phobos/druntine allocate liberally - the CRT almost never allocates
>>
>
> It's just most of CRT has incredibly bad usability, partly because it lack _any_ notion of allocators. And policy of using statically allocated shared data like in localtime, srand etc. shown remarkably bad M-T scalability.
>

I agree to an extent. Most C API's tend to expect you to provide the result
buffer, and that doesn't seem to be the prevailing pattern in D.
Some might argue it's ugly to pass a result buffer in, and I agree to an
extent, but I'll take it every time over the library violating my apps
allocation patterns.


Who actually uses shared_ptr?
>>
>
> Like everybody? Though with c++11 move semantics a unique_ptr is going to
> lessen it's widespread use. And there are ways to spend less then 2 proper
> memory allocations per shared_ptr, like keeping special block allocator for
> ref-counters.
> More importantly smart pointers are here to stay in C++.


Everybody eh.. :)
Well speaking from within the games industry at least, there's a prevailing
trend back towards flat C or C-like C++, many lectures and talks on the
topic. I have no contact with any C++ programmers that use STL beyond the
most trivial containers like vector. Many games companies re-invent some
stl-ish thing internally which is less putrid ;)
Additionally, I can't think of many libraries I've used that go hard-out
C++. Most popular libraries are very conservative, or even flat C (most old
stable libs that EVERYONE uses, zlib, png, jpeg, mad, tinyxml, etc). Havoc,
PhysX, FMod, etc are C++, but very light C++, light classes, no STL, etc.
Unreal used to use STL... but they fixed it :P


March 06, 2012
On 06.03.2012 18:10, Manu wrote:
> On 6 March 2012 15:10, Timon Gehr <timon.gehr@gmx.ch
> <mailto:timon.gehr@gmx.ch>> wrote:
>
>     On 03/06/2012 01:27 PM, Manu wrote:
>
>         concatenation, etc performs bucket loads of implicit GC
>         allocations
>
>
>     a~b
>
>     Nothing implicit about that.
>
>
> That is the very definition of an implicit allocation. What about the
> concatenation operator says that an allocation is to be expected?
> And what if you do a sequence of concatenations: a ~ b ~ c, now I've
> even created a redundant intermediate allocation. Will it be cleaned up
> immediately?

Just make an enhancement request ;)
Anyway it's good point as long as GC stays sloppy.

> Is there a convenient syntax to concatenate into a target buffer
> (subverting the implicit allocation)? If the syntax isn't equally
> convenient, nobody will use it.
>
>         This is my single biggest fear in D. I have explicit control
>         within my
>         own code, but I wonder if many D libraries will be sloppy and
>         over-allocate all over the place, and be generally unusable in many
>         applications.
>
>
>     IMHO this fear is unjustified. If the library developers are that
>     sloppy, chances are that the library is not worth using, even when
>     leaving all memory allocation concerns away. (It is likely that you
>     aren't the only programmer familiar with some of the issues.)
>
>
> I don't think it is unjustified, this seems to be the rule in C/C++
> rather than the exception, and there's nothing in D to suggest this will
> be mitigated, possibly worsened...
> Many libraries which are perfectly usable in any old 'app' are not
> usable in a realtime or embedded apps purely due to its internal
> design/allocation habits.
> Hopefully the D library authors will be more receptive to criticism...
> but I doubt it. I think it'll be exactly as it is in C/C++ currently.
>
>             Consider C strings. You need to keep track of ownership of
>         it. That
>             often means creating extra copies, rather than sharing a
>         single copy.
>
>
>         Rubbish, strings are almost always either refcounted
>
>
>     Technically, refcounting is a form of GC.
>
>
> Not really, it doesn't lock up the app at a random time for an
> indeterminate amount of time.
>
>
>         or on the stack for
>         dynamic strings, or have fixed memory allocated within structures. I
>         don't think I've ever seen someone duplicating strings into separate
>         allocations liberally.
>
>
>     It is impossible to slice a zero-terminated string without copying
>     it in the general case and refcounting slices is not trivial.
>
>
> This is when stack buffers are most common in C.
>
>         Who actually uses shared_ptr? Talking about the stl is
>         misleading... an
>
>         overwhelming number of C/C++ programmers avoid the stl like the
>         plague
>         (for these exact reasons). Performance oriented programmers
>         rarely use
>         STL out of the box, and that's what we're talking about here right?
>
>
>     Possibly now you are the one who is to provide supporting statistics.
>
>
> Touche :)
>
>         If you're not performance oriented, then who cares about the GC
>         either?
>
>
>     There is a difference between not performance oriented and
>     performance agnostic. Probably everyone cares about performance to
>     some extent.
>
>
> True.
>
>
> On 6 March 2012 15:13, Dmitry Olshansky <dmitry.olsh@gmail.com
> <mailto:dmitry.olsh@gmail.com>> wrote:
>
>     On 06.03.2012 16:27, Manu wrote:
>
>            Phobos/druntine allocate liberally - the CRT almost never
>         allocates
>
>
>     It's just most of CRT has incredibly bad usability, partly because
>     it lack _any_ notion of allocators. And policy of using statically
>     allocated shared data like in localtime, srand etc. shown remarkably
>     bad M-T scalability.
>
>
> I agree to an extent. Most C API's tend to expect you to provide the
> result buffer,
...pointer and it's supposed length and then do something sucky if it doesn't fit, like truncate it (strncpy I'm looking at you!).

and that doesn't seem to be the prevailing pattern in D.

There are better abstractions then "pass a buffer".

> Some might argue it's ugly to pass a result buffer in, and I agree to an
> extent, but I'll take it every time over the library violating my apps
> allocation patterns.
>
>         Who actually uses shared_ptr?
>
>
>     Like everybody? Though with c++11 move semantics a unique_ptr is
>     going to lessen it's widespread use. And there are ways to spend
>     less then 2 proper memory allocations per shared_ptr, like keeping
>     special block allocator for ref-counters.
>     More importantly smart pointers are here to stay in C++.
>
>
> Everybody eh.. :)
> Well speaking from within the games industry at least, there's a
> prevailing trend back towards flat C or C-like C++, many lectures and
> talks on the topic. I have no contact with any C++ programmers that use
> STL beyond the most trivial containers like vector. Many games companies
> re-invent some stl-ish thing internally which is less putrid ;)
> Additionally, I can't think of many libraries I've used that go hard-out
> C++. Most popular libraries are very conservative, or even flat C (most
> old stable libs that EVERYONE uses, zlib, png, jpeg, mad, tinyxml, etc).

Take into account how much discipline and manpower it took. Yet I remember the gory days when libpng segfaulted quite often ;)


> Havoc, PhysX, FMod, etc are C++, but very light C++, light classes, no
> STL, etc.

Havoc is pretty old btw, back in the days STL implementation + c++ compiler combination used to be slow and crappy, partly because of poor inlining. Here comes so-called "abstraction cost" it's almost the other way around nowdays.

> Unreal used to use STL... but they fixed it :P


-- 
Dmitry Olshansky
March 06, 2012
On Mar 6, 2012, at 4:27 AM, Manu <turkeyman@gmail.com> wrote:

> On 26 February 2012 00:55, Walter Bright <newshound2@digitalmars.com> wrote:
> On 2/25/2012 2:08 PM, Paulo Pinto wrote:
> Most standard compiler malloc()/free() implementations are actually slower than
> most advanced GC algorithms.
> 
> Most straight up GC vs malloc/free benchmarks miss something crucial. A GC allows one to do substantially *fewer* allocations. It's a lot faster to not allocate than to allocate.
> 
> Do you really think that's true? Are there any statistics to support that? I'm extremely sceptical of this claim.
> 
> I would have surely thought using a GC leads to a significant increase in allocations for a few reasons:
>   It's easy to allocate, ie, nothing to discourage you
>   It's easy to clean up - you don't have to worry about cleanup problems, makes it simpler to use in many situations
>   Dynamic arrays are easy - many C++ users will avoid dynamic arrays because the explicit allocation/clean up implies complexity, one will always use the stack, or a fixed array where they can get away with it
>   Slicing, concatenation, etc performs bucket loads of implicit GC allocations

Concatenation anyway.


>   Strings... - C coders who reject the stl will almost always have a separate string heap with very particular allocation patterns, and almost always refcounted
>   Phobos/druntine allocate liberally - the CRT almost never allocates
> 
> This is my single biggest fear in D. I have explicit control within my own code, but I wonder if many D libraries will be sloppy and over-allocate all over the place, and be generally unusable in many applications.
> If D is another language like C where the majority of libraries (including the standard libraries I fear) are unusable in various contexts, then that kinda defeats the purpose. D's module system is one of its biggest selling points.
> 
> I think there should be strict phobos allocation policies, and ideally, druntime should NEVER allocate if it can help it.

druntime already avoids allocations whenever possible. For example, core.demangle generates it's output in-place in a user-supplied buffer.

Regarding allocations in general, it's a matter of design philosophy. Tango, for example, basically never implicitly allocates. Phobos does. I'd say that Phobos is safer to program against and easier to use, but Tango affords more control for the discerning programmer. Personally, I'd like to see fewer implicit allocations in Phobos, but I think that ship has sailed.


> Consider C strings. You need to keep track of ownership of it. That often means creating extra copies, rather than sharing a single copy.
> 
> Rubbish, strings are almost always either refcounted or on the stack for dynamic strings, or have fixed memory allocated within structures. I don't think I've ever seen someone duplicating strings into separate allocations liberally.

I think the C standard library was designed with the intent that strings would be duplicated during processing, similar to D 's native string operations. It's true that people often use static buffers instead, but this has also been an enormous source of program bugs. Buffer overflow attacks wouldn't exist in C if people didn't do this. That said, I do it too. And I'll readily say that working with strings this way is a huge pain in the ass. It's just has more predictable performance.


> Enter C++'s shared_ptr. But that works by, for each object, allocating a *second* chunk of memory to hold the reference count. Right off the bat, you've got twice as many allocations & frees with shared_ptr than a GC would have.
> 
> Who actually uses shared_ptr? Talking about the stl is misleading... an overwhelming number of C/C++ programmers avoid the stl like the plague (for these exact reasons). Performance oriented programmers rarely use STL out of the box, and that's what we're talking about here right? If you're not performance oriented, then who cares about the GC either?

I've used it extensively. Managing memory ownership is one of the most complicated tasks in a C/C++ app, and in C++ this often means choosing the appropriate pointer type for the job--auto_ptr for transferral of ownership, shared_ptr, etc.

March 06, 2012
On Tue, Mar 6, 2012 at 5:27 AM, Manu <turkeyman@gmail.com> wrote:

> On 26 February 2012 00:55, Walter Bright <newshound2@digitalmars.com>wrote:
>
>> On 2/25/2012 2:08 PM, Paulo Pinto wrote:
>>
>>> Most standard compiler malloc()/free() implementations are actually
>>> slower than
>>> most advanced GC algorithms.
>>>
>>
>> Most straight up GC vs malloc/free benchmarks miss something crucial. A
>> GC allows one to do substantially *fewer* allocations. It's a lot faster to
>> not allocate than to allocate.
>>
>
> Do you really think that's true? Are there any statistics to support that? I'm extremely sceptical of this claim.
>
> I would have surely thought using a GC leads to a significant *increase*in allocations for a few reasons:
>   It's easy to allocate, ie, nothing to discourage you
>   It's easy to clean up - you don't have to worry about cleanup problems,
> makes it simpler to use in many situations
>   Dynamic arrays are easy - many C++ users will avoid dynamic arrays
> because the explicit allocation/clean up implies complexity, one will
> always use the stack, or a fixed array where they can get away with it
>   Slicing, concatenation, etc performs bucket loads of implicit GC
> allocations
>   Strings... - C coders who reject the stl will almost always have a
> separate string heap with very particular allocation patterns, and almost
> always refcounted
>   Phobos/druntine allocate liberally - the CRT almost never allocates
>
> This is my single biggest fear in D. I have explicit control within my own
> code, but I wonder if many D libraries will be sloppy and over-allocate all
> over the place, and be generally unusable in many applications.
> If D is another language like C where the majority of libraries (including
> the standard libraries I fear) are unusable in various contexts, then that
> kinda defeats the purpose. D's module system is one of its biggest selling
> points.
>
> I think there should be strict phobos allocation policies, and ideally, druntime should NEVER allocate if it can help it.
>
>
> Consider C strings. You need to keep track of ownership of it. That often
>> means creating extra copies, rather than sharing a single copy.
>>
>
> Rubbish, strings are almost always either refcounted or on the stack for dynamic strings, or have fixed memory allocated within structures. I don't think I've ever seen someone duplicating strings into separate allocations liberally.
>
>
Many STL implementers have abandoned COW (MSVC/Dinkumware, Clang's libc++, STLPort) and are instead using short-string-optimization.  Reference counted strings are seen as an anti-optimization in multithreaded code (especially since rvalue references were added making SSO even faster). [1]


>
>
>> Enter C++'s shared_ptr. But that works by, for each object, allocating a *second* chunk of memory to hold the reference count. Right off the bat, you've got twice as many allocations & frees with shared_ptr than a GC would have.
>>
>
> Who actually uses shared_ptr? Talking about the stl is misleading... an overwhelming number of C/C++ programmers avoid the stl like the plague (for these exact reasons). Performance oriented programmers rarely use STL out of the box, and that's what we're talking about here right? If you're not performance oriented, then who cares about the GC either?
>

That's certainly true, from what I hear, in the games industry but STL is heavily used outside of games.

Regards,
Brad Anderson

[1] http://www.gotw.ca/publications/optimizations.htm


March 06, 2012
On 2012-03-06 17:31, Sean Kelly wrote:
> On Mar 6, 2012, at 4:27 AM, Manu <turkeyman@gmail.com
> <mailto:turkeyman@gmail.com>> wrote:
>
>> On 26 February 2012 00:55, Walter Bright <newshound2@digitalmars.com
>> <mailto:newshound2@digitalmars.com>> wrote:
>>
>>     On 2/25/2012 2:08 PM, Paulo Pinto wrote:
>>
>>         Most standard compiler malloc()/free() implementations are
>>         actually slower than
>>         most advanced GC algorithms.
>>
>>
>>     Most straight up GC vs malloc/free benchmarks miss something
>>     crucial. A GC allows one to do substantially *fewer* allocations.
>>     It's a lot faster to not allocate than to allocate.
>>
>>
>> Do you really think that's true? Are there any statistics to support that?
>> I'm extremely sceptical of this claim.
>>
>> I would have surely thought using a GC leads to a significant
>> *increase* in allocations for a few reasons:
>> It's easy to allocate, ie, nothing to discourage you
>> It's easy to clean up - you don't have to worry about cleanup
>> problems, makes it simpler to use in many situations
>> Dynamic arrays are easy - many C++ users will avoid dynamic arrays
>> because the explicit allocation/clean up implies complexity, one will
>> always use the stack, or a fixed array where they can get away with it
>> Slicing, concatenation, etc performs bucket loads of implicit GC
>> allocations
>
> Concatenation anyway.
>
>
>> Strings... - C coders who reject the stl will almost always have a
>> separate string heap with very particular allocation patterns, and
>> almost always refcounted
>> Phobos/druntine allocate liberally - the CRT almost never allocates
>>
>> This is my single biggest fear in D. I have explicit control within my
>> own code, but I wonder if many D libraries will be sloppy and
>> over-allocate all over the place, and be generally unusable in many
>> applications.
>> If D is another language like C where the majority of libraries
>> (including the standard libraries I fear) are unusable in various
>> contexts, then that kinda defeats the purpose. D's module system is
>> one of its biggest selling points.
>>
>> I think there should be strict phobos allocation policies, and
>> ideally, druntime should NEVER allocate if it can help it.
>
> druntime already avoids allocations whenever possible. For example,
> core.demangle generates it's output in-place in a user-supplied buffer.
>
> Regarding allocations in general, it's a matter of design philosophy.
> Tango, for example, basically never implicitly allocates. Phobos does.
> I'd say that Phobos is safer to program against and easier to use, but
> Tango affords more control for the discerning programmer. Personally,
> I'd like to see fewer implicit allocations in Phobos, but I think that
> ship has sailed.

I have not seen any evidence that Tango would be less safe than Phobos. Tango uses buffers to let the user optionally pre-allocate buffers. But if the user doesn't, or the buffer is too small, Tango will allocate the buffer.

-- 
/Jacob Carlborg
March 07, 2012
On 3/6/2012 4:27 AM, Manu wrote:
> On 26 February 2012 00:55, Walter Bright <newshound2@digitalmars.com
>     Most straight up GC vs malloc/free benchmarks miss something crucial. A GC
>     allows one to do substantially *fewer* allocations. It's a lot faster to not
>     allocate than to allocate.
> Do you really think that's true?

Yes.

> Are there any statistics to support that?

No, just my experience using both.

Consider strings. In C, I'd often have a function that returns a string. The caller then (eventually) free's it. That means the string must have been allocated by malloc. That means that if I want to:

   return "foo";

I have to replace it with:

   return strdup("foo");

It means I can't do the "small string" optimization. It means I cannot return the tail of some other string. I cannot return a malloc'd string that anything else points to. I *must* return a *unique* malloc'd string.

This carries into a lot of data structures, and means lots of extra allocations.

Next problem: I can't do array slicing. I have to make copies instead.

You suggested using ref counting. That's only a partial solution. Setting aside all the problems of getting it right, consider getting a stream of input from a user. With GC, you can slice it and store those slices in a symbol table - no allocations at all. No chance of that without a GC, even with ref counting.
March 07, 2012
Slicing works, it just requires more care. GC makes slicing work pretty much automatically, though you can end up with severe memory bloat.

On Mar 6, 2012, at 6:25 PM, Walter Bright <newshound2@digitalmars.com> wrote:

> On 3/6/2012 4:27 AM, Manu wrote:
>> On 26 February 2012 00:55, Walter Bright <newshound2@digitalmars.com
>>    Most straight up GC vs malloc/free benchmarks miss something crucial. A GC
>>    allows one to do substantially *fewer* allocations. It's a lot faster to not
>>    allocate than to allocate.
>> Do you really think that's true?
> 
> Yes.
> 
>> Are there any statistics to support that?
> 
> No, just my experience using both.
> 
> Consider strings. In C, I'd often have a function that returns a string. The caller then (eventually) free's it. That means the string must have been allocated by malloc. That means that if I want to:
> 
>   return "foo";
> 
> I have to replace it with:
> 
>   return strdup("foo");
> 
> It means I can't do the "small string" optimization. It means I cannot return the tail of some other string. I cannot return a malloc'd string that anything else points to. I *must* return a *unique* malloc'd string.
> 
> This carries into a lot of data structures, and means lots of extra allocations.
> 
> Next problem: I can't do array slicing. I have to make copies instead.
> 
> You suggested using ref counting. That's only a partial solution. Setting aside all the problems of getting it right, consider getting a stream of input from a user. With GC, you can slice it and store those slices in a symbol table - no allocations at all. No chance of that without a GC, even with ref counting.
March 07, 2012
On 3/6/2012 7:19 PM, Sean Kelly wrote:
> Slicing works, it just requires more care.

You can't mix sliced data and unsliced, unless you have extra data in your structures to track this.

> GC makes slicing work pretty much automatically, though you can end up with severe memory bloat.

I don't see how slicing produces bloat.
March 07, 2012
On Mar 6, 2012, at 7:47 PM, Walter Bright wrote:

> On 3/6/2012 7:19 PM, Sean Kelly wrote:
>> Slicing works, it just requires more care.
> 
> You can't mix sliced data and unsliced, unless you have extra data in your structures to track this.

Ah, I see what you're saying.  True.


>> GC makes slicing work pretty much automatically, though you can end up with severe memory bloat.
> 
> I don't see how slicing produces bloat.

Slice ten bytes out of the middle of a ten MB buffer and the entire buffer sticks around.
March 07, 2012
On Wednesday, 7 March 2012 at 02:25:41 UTC, Walter Bright wrote:
> On 3/6/2012 4:27 AM, Manu wrote:
>> On 26 February 2012 00:55, Walter Bright <newshound2@digitalmars.com
>>    Most straight up GC vs malloc/free benchmarks miss something crucial. A GC
>>    allows one to do substantially *fewer* allocations. It's a lot faster to not
>>    allocate than to allocate.
>> Do you really think that's true?
>
> Yes.

I think you're both right. GC does definitely allow you to do less allocations, but as Manu said it also makes people more allocation happy.


>> Are there any statistics to support that?
>
> No, just my experience using both.
>
> Consider strings. In C, I'd often have a function that returns a string. The caller then (eventually) free's it. That means the string must have been allocated by malloc.

I'd say it is bad design to return a malloc'd string. You should take a destination buffer as an argument and put the string there (like strcpy and friends). That way you can do whatever you want.

Sean made the good point that using buffers like that can lead to errors, but D's arrays make things a lot safer.