www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Preferred method of creating objects, structs, and arrays with

reply Anthony Monterrosa <Anthony.Monterrosa rocky.edu> writes:
I've recently been trying to convince a friend of mine that D has 
at least the functionality of C++, and have been learning the 
language over C++ for a few months. Memory management is pretty 
important to him, and a subject I'm honestly curious about as 
well. I was wondering: what's the preferred method for 
deterministic memory management?

I don't know much about this topic relative to most (Java 
background), but this is what I've found:

  - Classes/Structs have constructors and destructors. I am 
unconfident with my knowledge as to how this works with malloc 
and free.

  - core.memory can be used to call malloc and its buddies. It 
allows determined management, but will still use the GC if 
something isn't collected (presumably for leaks).

- Many features and types use the GC such as exceptions, the new 
keyword, and all arrays except statics.

  - Allocators in "std.experimental.allocators" still use the GC, 
but give more control for class/struct objects.

  - std.container.array can be used for deterministic arrays, but 
has the issue of dangling pointers. There is probably a good 
solution to this, but I don't know it.

  - There seems to be no way to completely turn off the GC. That 
is, never have the runtime allocate the memory used by the GC.

  - Andreau had a discussion in 2009 about how this issue might be 
handled, but there didn't seem to be an obvious consensus 
(http://forum.dlang.org/thread/hafpjn$1cu8$1 digitalmars.com?page=1)

This are the pieces I've gathered, but I don't really know what's 
true or how to use this knowledge. Some ideas I've gleaned may 
also be outdated. Does anyone know the "correct" way one would go 
about a non-GC program, and if a program can be ran without ever 
instantiating a GC? Has there been any progress on reducing the 
std library's usage of the GC?
Jun 01 2016
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 01/06/2016 7:59 PM, Anthony Monterrosa wrote:
 I've recently been trying to convince a friend of mine that D has at
 least the functionality of C++, and have been learning the language over
 C++ for a few months. Memory management is pretty important to him, and
 a subject I'm honestly curious about as well. I was wondering: what's
 the preferred method for deterministic memory management?

 I don't know much about this topic relative to most (Java background),
 but this is what I've found:

  - Classes/Structs have constructors and destructors. I am unconfident
 with my knowledge as to how this works with malloc and free.
They get called once memory has been allocated and before it is deallocated.
  - core.memory can be used to call malloc and its buddies. It allows
 determined management, but will still use the GC if something isn't
 collected (presumably for leaks).
No. core.memory provides an interface to the GC, not malloc and friends.
 - Many features and types use the GC such as exceptions, the new
 keyword, and all arrays except statics.
Not all arrays. Slices are not required to use the GC, just don't go appending to it.
  - Allocators in "std.experimental.allocators" still use the GC, but
 give more control for class/struct objects.
GCAllocator uses the GC yes. It is the default one for theAllocator() and processAllocator(). However there are others such as Mallocator which do not use the GC but directly call malloc and friends.
  - std.container.array can be used for deterministic arrays, but has the
 issue of dangling pointers. There is probably a good solution to this,
 but I don't know it.

  - There seems to be no way to completely turn off the GC. That is,
 never have the runtime allocate the memory used by the GC.
Oh but you can! https://github.com/dlang/druntime/blob/master/src/gcstub/gc.d Now imagine replacing all those useful little function implementations with assert(0); Then you can never use the GC!
  - Andreau had a discussion in 2009 about how this issue might be
 handled, but there didn't seem to be an obvious consensus
 (http://forum.dlang.org/thread/hafpjn$1cu8$1 digitalmars.com?page=1)

 This are the pieces I've gathered, but I don't really know what's true
 or how to use this knowledge. Some ideas I've gleaned may also be
 outdated. Does anyone know the "correct" way one would go about a non-GC
 program, and if a program can be ran without ever instantiating a GC?
 Has there been any progress on reducing the std library's usage of the GC?
People view the GC as a bad thing. Most of the time it is only ever a good thing. You're not writing a AAA game here and even then you might be able to get away with it by just being a little bit careful and disabling it. If you have some code that needs to be speed up? Sure preallocate memory will always give you speed boosts. But the GC generally won't cause that many problems especially if its disabled for the hot places.
Jun 01 2016
prev sibling next sibling parent Seb <seb wilzba.ch> writes:
On Wednesday, 1 June 2016 at 07:59:50 UTC, Anthony Monterrosa 
wrote:
 I've recently been trying to convince a friend of mine that D 
 has at least the functionality of C++, and have been learning 
 the language over C++ for a few months. Memory management is 
 pretty important to him, and a subject I'm honestly curious 
 about as well. I was wondering: what's the preferred method for 
 deterministic memory management?

 [...]
You should watch this year's dconf keynote. The plan is to make the GC usage opt-in. There is also the company weka that does high performance storage and turned off the gc entirely and allocates all exception on startup.vstartup. Their CTO gave a really nice talk too. http://dconf.org/2016/talks/zvibel.html If you want to convince your friend, tell him that using the GC is more productive and he still can do manual memory management or use RefCounted if really needed for the performance. That being said also reference counting and other techniques come at a cost. Btw The videos aren't up yet, but the live stream is archived.
Jun 01 2016
prev sibling parent reply Rene Zwanenburg <renezwanenburg gmail.com> writes:
 I was wondering: what's the preferred method for deterministic 
 memory management?
You may be interested in RefCounted. It only works for structs, not classes, but it's still useful.
  - Classes/Structs have constructors and destructors. I am 
 unconfident with my knowledge as to how this works with malloc 
 and free.
malloc() and free() operate on a lower level, they only care about raw memory. When you malloc() some space, you can construct an object there using emplace(), and it can be destructed by using detroy().
 - Many features and types use the GC such as exceptions, the 
 new keyword, and all arrays except statics.
It's important to differentiate static arrays, and slices with static storage. For example: class C { static int[] someSlice; // This is a slice with static storage. The memory it is referring to may be GC allocated, but it doesn't have to (this is true for all slices btw). int[4] someStaticArray; // This is a static array, i.e. an array with a fixed length. In D static arrays are value types, so it's allocated in its enclosing scope and copied when you pass it around. }
  - std.container.array can be used for deterministic arrays, 
 but has the issue of dangling pointers. There is probably a 
 good solution to this, but I don't know it.
I don't know of any dangling pointer issues with Array. It's possible to create cycles resulting in a leak, but that's only likely to happen if you heavily rely on refcounting everything.
  - There seems to be no way to completely turn off the GC. That 
 is, never have the runtime allocate the memory used by the GC.
Like Rikki said, if you really want to the GC can be replaced with an asserting stub. This isn't as hard as it sounds, just add something like the file he linked to to your project. Since all declarations are extern(C) there is no name mangling, and the linker will prefer your own definitions over the ones in druntime. I don't recommend you do this though unless you really know what you're doing.
 This are the pieces I've gathered, but I don't really know 
 what's true or how to use this knowledge. Some ideas I've 
 gleaned may also be outdated. Does anyone know the "correct" 
 way one would go about a non-GC program, and if a program can 
 be ran without ever instantiating a GC? Has there been any 
 progress on reducing the std library's usage of the GC?
You can annotate your functions as nogc. The compiler will disallow any potential GC use, including calling other functions that are not nogc. P0nce is doing real time audio stuff, iirc he's using a thread with a nogc entry point for the strictly real-time parts, and regular GC-using code in another thread for everything else.
Jun 01 2016
parent Guillaume Piolat <first.last gmail.com> writes:
On Wednesday, 1 June 2016 at 08:53:01 UTC, Rene Zwanenburg wrote:
 I was wondering: what's the preferred method for deterministic 
 memory management?
You can annotate your functions as nogc. The compiler will disallow any potential GC use, including calling other functions that are not nogc. P0nce is doing real time audio stuff, iirc he's using a thread with a nogc entry point for the strictly real-time parts, and regular GC-using code in another thread for everything else.
Yes, GC is a minor concern for me. I'm happy to use the GC in UI stuff next to the nogc part. As tired as the expression is, it's a "best of both world" situation. I tried GC.disable(), it was bringing lots of stability problems because not all my code was nogc and rogue allocations occured. I guess I deserved it? I'm a heavy user of the GC-proof resource class "idiom" which turn your turn the GC into a leak detector: https://p0nce.github.io/d-idioms/#GC-proof-resource-class That way you can make polymorphic resources with relative safety. Exception safety is harder though for class objects. Usually struct should be used. I'd say D has a more complex story for resources, but it's not necessary a bad story. When writing a writeln("hello world"); I don't really want to think about who owns the string "hello world". That's what affine types are about, one size fits all.
Jun 01 2016