Thread overview
[Issue 20219] Idle D programs keep consuming CPU in Gcx.scanBackground
Sep 17, 2019
Dlang Bot
Sep 17, 2019
Rainer Schuetze
Sep 17, 2019
Vladimir Panteleev
Sep 18, 2019
Rainer Schuetze
Sep 18, 2019
Vladimir Panteleev
Sep 18, 2019
Rainer Schuetze
Sep 27, 2019
Dlang Bot
September 17, 2019
https://issues.dlang.org/show_bug.cgi?id=20219

--- Comment #1 from Dlang Bot <dlang-bot@dlang.rocks> ---
@rainers created dlang/druntime pull request #2802 "Issue 20219 - Idle D programs keep consuming CPU in Gcx.scanBackground" mentioning this issue:

- Issue 20219 - Idle D programs keep consuming CPU in Gcx.scanBackground

  background scan threads now wait indefinitely, with termination continuously
triggering the condition until all threads have woken up

https://github.com/dlang/druntime/pull/2802

--
September 17, 2019
https://issues.dlang.org/show_bug.cgi?id=20219

--- Comment #2 from Rainer Schuetze <r.sagitario@gmx.de> ---
I've been bothered by the idle CPU time recently too.

Not sure what to do about the additional threads staying around forever, maybe they could terminate after some time of not running, but that adds considerable overhead when restarting them.

It seems that the parallel marking has worked out without much troubles (better than expected). When making it opt-in, only few programs would actually benefit from that, because people won't bother to change the defaults.

--
September 17, 2019
https://issues.dlang.org/show_bug.cgi?id=20219

--- Comment #3 from Vladimir Panteleev <dlang-bugzilla@thecybershadow.net> ---
(In reply to Rainer Schuetze from comment #2)
> Not sure what to do about the additional threads staying around forever, maybe they could terminate after some time of not running, but that adds considerable overhead when restarting them.

How costly is this overhead?

I think your suggestion is a good idea, and we should balance the time the threads stay idle with the overhead of starting them. E.g.: let them shut down if they have been idle for more than 100x-1000x the time that would be needed to start them again.

(In reply to Rainer Schuetze from comment #2)
> When making it opt-in, only few programs would
> actually benefit from that, because people won't bother to change the
> defaults.

Not sure what you're trying to say, as this argument applies to both opt-in and opt-out, with each being a compromise.

What I'm worried about of, if this were to become normalized, reactions like "Why does this tiny program I just installed need so many threads? Oh right, it's written in D, that language with that bloated runtime and garbage collector which needs a dozen threads to work properly. What a mess, why hasn't someone rewritten it in Rust yet!".

--
September 18, 2019
https://issues.dlang.org/show_bug.cgi?id=20219

--- Comment #4 from Rainer Schuetze <r.sagitario@gmx.de> ---
(In reply to Vladimir Panteleev from comment #3)
> How costly is this overhead?

I don't have hard numbers, but IIRC the overhead was a couple of ms for tests that only ever run a single collection.

> 
> I think your suggestion is a good idea, and we should balance the time the threads stay idle with the overhead of starting them. E.g.: let them shut down if they have been idle for more than 100x-1000x the time that would be needed to start them again.

Possible, but I'm not sure it is worth the effort. The threads use only a small stack of 16kB and are now just waiting for a common event.

> 
> (In reply to Rainer Schuetze from comment #2)
> > When making it opt-in, only few programs would
> > actually benefit from that, because people won't bother to change the
> > defaults.
> 
> Not sure what you're trying to say, as this argument applies to both opt-in and opt-out, with each being a compromise.

True, it's a compromise trading some thread handles and memory for better performance in most cases. I suspect most people (and especially the users of the program more than the developer) want the program to run faster, so the default should be that.

> 
> What I'm worried about of, if this were to become normalized, reactions like "Why does this tiny program I just installed need so many threads? Oh right, it's written in D, that language with that bloated runtime and garbage collector which needs a dozen threads to work properly. What a mess, why hasn't someone rewritten it in Rust yet!".

When I start any program in a debugger on Windows, I see 3 additional threads already running for that process when entering WinMain. I haven't seen any complaints about that.

--
September 18, 2019
https://issues.dlang.org/show_bug.cgi?id=20219

--- Comment #5 from Vladimir Panteleev <dlang-bugzilla@thecybershadow.net> ---
(In reply to Rainer Schuetze from comment #4)
> I don't have hard numbers, but IIRC the overhead was a couple of ms for tests that only ever run a single collection.

Then, would you agree that terminating the threads after a few seconds of inactivity would be appropriate?

> Possible, but I'm not sure it is worth the effort. The threads use only a small stack of 16kB and are now just waiting for a common event.

I can look into implementing this if we agree otherwise.

> True, it's a compromise trading some thread handles and memory for better performance in most cases. I suspect most people (and especially the users of the program more than the developer) want the program to run faster, so the default should be that.

I think I would agree that GC speed is overall more important, though I don't think we have the data for how D is used to make hard conclusions about which tradeoff is better. It might be possible that GC speed would not be a large factor of the performance of a typical D program? Most D users already must undergo an additional step for their D programs to perform reasonably, which is to switch to the GDC or LDC compiler.

> When I start any program in a debugger on Windows, I see 3 additional threads already running for that process when entering WinMain. I haven't seen any complaints about that.

The situation on other platforms might very well be different. I don't think Windows has received nearly the same level of scrutiny about not wastefully using resources as FOSS operating systems. Would you suggest making the default behavior depend on the current OS?

--
September 18, 2019
https://issues.dlang.org/show_bug.cgi?id=20219

--- Comment #6 from Rainer Schuetze <r.sagitario@gmx.de> ---
(In reply to Vladimir Panteleev from comment #5)
> Then, would you agree that terminating the threads after a few seconds of inactivity would be appropriate?

I'd be ok with this (or maybe a slightly larger timeout) if it doesn't complicate the handling too much.

> The situation on other platforms might very well be different. I don't think Windows has received nearly the same level of scrutiny about not wastefully using resources as FOSS operating systems. Would you suggest making the default behavior depend on the current OS?

Fine with me. My initial suggestion was actually to make it opt-in (https://github.com/dlang/druntime/pull/2514#issuecomment-478285235), but there were no complaints while it was enabled ;-) But maybe it wasn't stress tested enough.

--
September 27, 2019
https://issues.dlang.org/show_bug.cgi?id=20219

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--- Comment #7 from Dlang Bot <dlang-bot@dlang.rocks> ---
dlang/druntime pull request #2802 "Issue 20219 - Idle D programs keep consuming CPU in Gcx.scanBackground" was merged into stable:

- 18ca55405eed87ce45e84e11dba14debf0346266 by Rainer Schuetze:
  fix issue 20219 - Idle D programs keep consuming CPU in Gcx.scanBackground

  background scan threads now wait indefinitely, with termination continuously
triggering the condition until all threads have woken up

https://github.com/dlang/druntime/pull/2802

--