January 15, 2021
On Friday, 15 January 2021 at 16:21:18 UTC, Ola Fosheim Grøstad wrote:

> What do you mean by "mix and match"? If it means shutting down the GC after initialization then it can easily backfire for more complicated software that accidentally calls code that relies on the GC.

I mean: "using GC, unless where it creates problems". Examples below.

> Until someone can describe a strategy that works for a full application, e.g. an animation-editor or something like that, it is really difficult to understand what is meant by it.

Personal examples:
 - The game Vibrant uses GC for some long-lived objects.
   Memory pools for most game entities.
   Audio thread has disabled GC.

- Dplug plugins before runtime removal used GC in the UI, but no GC in whatever was called repeatedly, leading to no GC pause in practice. In case an error was made, it would be a GC pause, but not a leak.

The pain point with the mixed approach is adding GC roots when needed. You need a mental model of traceability.

It really is quite easy to do: build you app normally, evetually optimize later by using manual memory management.
January 15, 2021
On Friday, 15 January 2021 at 16:21:43 UTC, jmh530 wrote:
> On Friday, 15 January 2021 at 15:36:37 UTC, Ola Fosheim Grøstad wrote:
> The library smart pointers would make it difficult to interact with existing D GC code though.

Yes. So it would be better to do it automatically in the compiler for designated GC objects.

ARC is also a good alternative.

Probably less work to get a high quality ARC implementation, than a high quality GC implementation.

January 15, 2021
On Friday, 15 January 2021 at 16:26:59 UTC, Guillaume Piolat wrote:
>> Until someone can describe a strategy that works for a full application, e.g. an animation-editor or something like that, it is really difficult to understand what is meant by it.
>
> Personal examples:
>  - The game Vibrant uses GC for some long-lived objects.
>    Memory pools for most game entities.
>    Audio thread has disabled GC.

But when do you call collect? Do you not create more and more long-lived objects?

> - Dplug plugins before runtime removal used GC in the UI, but no GC in whatever was called repeatedly, leading to no GC pause in practice. In case an error was made, it would be a GC pause, but not a leak.

How do you structure this? Limit GC to one main thread? But an audio plugin GUI is not used frequently, so... hickups are less noticable. For a 3D or animation editor hickups would be very annoying.

> The pain point with the mixed approach is adding GC roots when needed. You need a mental model of traceability.

Yes. I tend to regret "clever" solutions when getting back to the code months later because the mental model is no longer easily available.

I think it is better with something simpler like saying one GC per thread, or ARC across the board unless you use non-arc pointers, or that only class objects are GC. Basically something that creates a simple mental model.

> It really is quite easy to do: build you app normally, evetually optimize later by using manual memory management.

I understand what you are saying, but it isn't all that much more work to use explicit ownership if all the libraries have support for it.

It is a lot more work to add manual memory management if the available libraries don't help you out.


January 15, 2021
On Fri, Jan 15, 2021 at 04:22:59PM +0000, IGotD- via Digitalmars-d-learn wrote: [...]
> Are we talking about the same things here? You mentioned DMD but I was talking about programs compiled with DMD (or GDC, LDC), not the nature of the DMD compiler in particular.
> 
> Bump the pointer and never return any memory might acceptable for short lived programs but totally unacceptable for long running programs, like a browser you are using right now.
> 
> Just to clarify, in a program that is made in D with the default options, will there be absolutely no memory reclamation?

We're apparently cross-talking here.  A default D program uses the GC, as should be obvious by now.  DMD itself, however, uses bump-the-pointer (*not* programs it compiles, though!).  The two are completely unrelated.


T

-- 
Let X be the set not defined by this sentence...
January 15, 2021
On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote:
> I've always heard programmers complain about Garbage Collector GC. But I never understood why they complain. What's bad about GC?

Most people get to know GC trough Java or C#. Those languages promote the use of OOP and they say that you dont need to worry about memory management. The result is that people write code that doesnt utilize CPU caches effectively and makes a lot of temporary allocations. For example people at Microsoft implemented json parser in C# and it would allocate 8GB of memory for every 1GB parsed. Add to that virtual machines and you find that programs written in those languages run like they are coded in molasse.

People with experience of those programs conclude that is all because of GC. And its simple explanation for simple people.
January 15, 2021
On Friday, 15 January 2021 at 16:22:59 UTC, IGotD- wrote:
> [snip]
>
> Are we talking about the same things here? You mentioned DMD but I was talking about programs compiled with DMD (or GDC, LDC), not the nature of the DMD compiler in particular.
>
> Bump the pointer and never return any memory might acceptable for short lived programs but totally unacceptable for long running programs, like a browser you are using right now.
>
> Just to clarify, in a program that is made in D with the default options, will there be absolutely no memory reclamation?

You are talking about different things.

DMD, as a program, uses the bump the pointer allocation strategy.

If you compile a D program with DMD that uses new or appends to a dynamic array (or whenver else), then it is using the GC to do that. You can also use malloc or your own custom strategy. The GC will reclaim memory, but there is no guarantee that malloc or a custom allocation strategy will.
January 15, 2021
On Friday, 15 January 2021 at 16:37:46 UTC, Ola Fosheim Grøstad wrote:
>
> But when do you call collect? Do you not create more and more long-lived objects?

Calling collect() isn't very good, it's way better to ensure the GC heap is relatively small, hence easy to traverse.
You can use -gc=profile for this (noting that things that can't contain pointer, such as ubyte[], scan way faster than void[])

>
> How do you structure this? Limit GC to one main thread? But an audio plugin GUI is not used frequently, so... hickups are less noticable. For a 3D or animation editor hickups would be very annoying.

Yes but when a hiccup happen you can often trace it back to gargage generation and target it. It's an optimization task.


> I think it is better with something simpler like saying one GC per thread

But then ownership doesn't cross threads, so it can be tricky to keep object alive when they cross threads. I think that was a problem in Nim.


>> It really is quite easy to do: build you app normally, evetually optimize later by using manual memory management.
>
> I understand what you are saying, but it isn't all that much more work to use explicit ownership if all the libraries have support for it.

But sometimes that ownership is just not interesting. If you are writing a hello world program, no one cares who "hello world" string belongs to. So the GC is that global owner.
January 15, 2021
On Friday, 15 January 2021 at 18:43:44 UTC, Guillaume Piolat wrote:
> Calling collect() isn't very good, it's way better to ensure the GC heap is relatively small, hence easy to traverse.
> You can use -gc=profile for this (noting that things that can't contain pointer, such as ubyte[], scan way faster than void[])

Ok, so what you basically say is that the number of pointers to trace was small, and perhaps also the render thread was not under GC control?

>> I think it is better with something simpler like saying one GC per thread
>
> But then ownership doesn't cross threads, so it can be tricky to keep object alive when they cross threads. I think that was a problem in Nim.

What I have proposed before is to pin down objects with a ref count when you temporarily hand them to other threads. Then the other thread will handle it with a smart_pointer which release the "borrow ref count" on return.

But yes, you "need" some way for other threads to borrow thread local memory, in order to implement async services etc.  Then again, I think people who write such service frameworks will be more advanced programmers than those that use them. So I wouldn't say it is a big downside.

> But sometimes that ownership is just not interesting. If you are writing a hello world program, no one cares who "hello world" string belongs to. So the GC is that global owner.

I get your viewpoint, but simple types like strings can be handled equally well with RC... If we take the view, that you also stressed, that it is desirable to keep the tracable pointer count down, then maybe making only class object GC is the better approach.
January 15, 2021
On Friday, 15 January 2021 at 18:55:27 UTC, Ola Fosheim Grøstad wrote:
> On Friday, 15 January 2021 at 18:43:44 UTC, Guillaume Piolat wrote:
>> Calling collect() isn't very good, it's way better to ensure the GC heap is relatively small, hence easy to traverse.
>> You can use -gc=profile for this (noting that things that can't contain pointer, such as ubyte[], scan way faster than void[])
>
> Ok, so what you basically say is that the number of pointers to trace was small, and perhaps also the render thread was not under GC control?

A small GC heap is sufficient.
There is this blog post where there was a quantitative measure of the sub-1ms D GC heap size.
http://www.infognition.com/blog/2014/the_real_problem_with_gc_in_d.html

> 200 KB can be scanned/collected in 1 ms.

Since then the D GC has improved in many ways (multicore, precise, faster...) that surprisingly have not been publicized that much ; but probably the suggested realtime heap size is in the same order of magnitude.

In this 200kb number above, things that can't contain pointers don't count.
January 15, 2021
On Friday, 15 January 2021 at 19:37:12 UTC, Guillaume Piolat wrote:
> A small GC heap is sufficient.
> There is this blog post where there was a quantitative measure of the sub-1ms D GC heap size.

That's ok for a small game, but not for applications that grow over time or projects where the requirement spec is written (and continually added to) by customers. But for enthusiast projects, that can work.

Many open source projects (and also some commercial ones) work ok for small datasets, but tank when you increase the dataset. So "match and mix" basically means use it for prototyping, but do-not-rely-on-it-if-you-can-avoid-it.

Switching to ARC looks more attractive, scales better and the overhead is more evenly distributed. But it probably won't happen.