Thread overview
D create many thread
Feb 05, 2020
Eko Wahyudin
Feb 05, 2020
MoonlightSentinel
Feb 05, 2020
Gregor Mückl
Feb 06, 2020
uranuz
Feb 07, 2020
rikki cattermole
Feb 06, 2020
tchaloupka
Feb 07, 2020
bauss
Feb 08, 2020
Rainer Schuetze
February 05, 2020
Hi all,

I'm create a small (hallo world) application, with DMD.
But my program create 7 annoying threads when create an empty class.

What is this thread for?
and is it normal in D?

Below the stack trace of thread creation.

#0  0x00007ffff7f637a0 in pthread_create@@GLIBC_2.2.5 () from /usr/lib/libpthread.so.0
#1  0x00005555557388d0 in core.thread.osthread.createLowLevelThread(void() nothrow delegate, uint, void() nothrow delegate) ()
#2  0x0000555555731384 in _D2gc4impl12conservativeQw3Gcx16startScanThreadsMFNbZv ()
#3  0x00005555557307ba in _D2gc4impl12conservativeQw3Gcx11fullcollectMFNbbZm ()
#4  0x000055555572eccc in _D2gc4impl12conservativeQw3Gcx10smallAllocMFNbmKmkxC8TypeInfoZPv ()
#5  0x00005555557346a9 in _D2gc4impl12conservativeQw14ConservativeGC__T9runLockedS_DQCeQCeQCcQCnQBs12mallocNoSyncMFNbmkKmxC8TypeInfoZPvS_DQEgQEgQEeQEp10mallocTimelS_DQFiQFiQFgQFr10numMallocslTmTkTmTxQCzZQFcMFNbKmKkKmKxQDsZQDl ()
#6  0x000055555572c2fe in _D2gc4impl12conservativeQw14ConservativeGC6mallocMFNbmkxC8TypeInfoZPv ()
#7  0x00005555556cd163 in gc_malloc ()
#8  0x00005555556f529c in _D2gc4impl5protoQo7ProtoGC6mallocMFNbmkxC8TypeInfoZPv ()
#9  0x00005555556cd163 in gc_malloc ()
#10 0x00005555556cf55b in _d_newclass ()
#11 0x00005555556669f4 in D main (args=...) at source/app.d:11
(gdb) info threads
  Id   Target Id                                Frame
* 1    Thread 0x7ffff7c1ea40 (LWP 8288) "jala2" 0x00007ffff7f637a0 in pthread_create@@GLIBC_2.2.5 () from /usr/lib/libpthread.so.0
  2    Thread 0x7ffff7fcc700 (LWP 8289) "jala2" 0x00007ffff7f69c45 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
  3    Thread 0x7ffff7fc7700 (LWP 8317) "jala2" 0x00007ffff7f69c45 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
  4    Thread 0x7ffff7fc2700 (LWP 8329) "jala2" 0x00007ffff7f69c45 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
  5    Thread 0x7ffff7fbd700 (LWP 8439) "jala2" 0x00007ffff7f69c45 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
  6    Thread 0x7ffff7fb8700 (LWP 8445) "jala2" 0x00007ffff7f69c45 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0
  7    Thread 0x7ffff7fb3700 (LWP 8463) "jala2" 0x00007ffff7f69c45 in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib/libpthread.so.0


Thank you in advance.
February 05, 2020
On Wednesday, 5 February 2020 at 13:05:59 UTC, Eko Wahyudin wrote:
> What is this thread for?
> and is it normal in D?

According to the stack trace your applications triggered a GC cycle. The marking is done in parallel to minimize pause times, see https://dlang.org/spec/garbage.html
February 05, 2020
On 2/5/20 8:05 AM, Eko Wahyudin wrote:
> Hi all,
> 
> I'm create a small (hallo world) application, with DMD.
> But my program create 7 annoying threads when create an empty class.
> 
> What is this thread for?
> and is it normal in D?

> Thank you in advance.

I didn't know about this feature. I was going to respond that it is not normal, but this was added almost a year ago.

First, I think this is a bit over the top. A hello world program should not spawn threads to aid in marking.

Looking at the PR that made this happen, I think the author originally had reservations about it: https://github.com/dlang/druntime/pull/2514#issuecomment-487090334

I think we should be more selective about when we make parallel threads to scan (maybe above a certain size of used memory?).

-Steve
February 05, 2020
On Wednesday, 5 February 2020 at 15:54:23 UTC, Steven Schveighoffer wrote:
> I think we should be more selective about when we make parallel threads to scan (maybe above a certain size of used memory?).
>
> -Steve

That threshold would have to adapt to each system. How about delaying thread startup until the first actual mark phase or the first run after the first 100ms of runtime or so? The main goal should be to minimize the runtime impact. It doesn't even make sense to me to run a GC cycle for a program that runs for a extremely short time only.
February 06, 2020
Is it also possible to set some custom thread name for GC threads in order to be distinguishable from other threads in utilities like `htop`? It would be handy...
February 06, 2020
On Wednesday, 5 February 2020 at 13:05:59 UTC, Eko Wahyudin wrote:
> Hi all,
>
> I'm create a small (hallo world) application, with DMD.
> But my program create 7 annoying threads when create an empty class.
>

If you don't want the parallel sweep enabled for your app, you can turn it of ie with:

```
extern(C) __gshared string[] rt_options = [ "gcopt=parallel:0" ];
```

Or in various other ways as described in mentioned documentation: https://dlang.org/spec/garbage.html#gc_config


February 07, 2020
On 07/02/2020 8:53 AM, uranuz wrote:
> Is it also possible to set some custom thread name for GC threads in order to be distinguishable from other threads in utilities like `htop`? It would be handy...

https://dlang.org/phobos/core_thread_osthread.html#.Thread.name.2
February 07, 2020
On Thursday, 6 February 2020 at 22:00:26 UTC, tchaloupka wrote:
> On Wednesday, 5 February 2020 at 13:05:59 UTC, Eko Wahyudin wrote:
>> Hi all,
>>
>> I'm create a small (hallo world) application, with DMD.
>> But my program create 7 annoying threads when create an empty class.
>>
>
> If you don't want the parallel sweep enabled for your app, you can turn it of ie with:
>
> ```
> extern(C) __gshared string[] rt_options = [ "gcopt=parallel:0" ];
> ```
>
> Or in various other ways as described in mentioned documentation: https://dlang.org/spec/garbage.html#gc_config

Why are we doing it like that? That's the least user-friendly method of configuring the GC I have ever seen.
February 07, 2020
On 2/7/20 2:34 AM, bauss wrote:
> On Thursday, 6 February 2020 at 22:00:26 UTC, tchaloupka wrote:
>> On Wednesday, 5 February 2020 at 13:05:59 UTC, Eko Wahyudin wrote:
>>> Hi all,
>>>
>>> I'm create a small (hallo world) application, with DMD.
>>> But my program create 7 annoying threads when create an empty class.
>>>
>>
>> If you don't want the parallel sweep enabled for your app, you can turn it of ie with:
>>
>> ```
>> extern(C) __gshared string[] rt_options = [ "gcopt=parallel:0" ];
>> ```
>>
>> Or in various other ways as described in mentioned documentation: https://dlang.org/spec/garbage.html#gc_config
> 
> Why are we doing it like that? That's the least user-friendly method of configuring the GC I have ever seen.

The reason this has to be configured this way is because the parallel scanning is an implementation detail, and shouldn't be exposed via the core.memory.GC interface.

But I still maintain, a hello world program should not need this to avoid spawning 6 threads to scan itself.

-Steve
February 08, 2020

On 07/02/2020 16:52, Steven Schveighoffer wrote:
> But I still maintain, a hello world program should not need this to avoid spawning 6 threads to scan itself.

I agree, see https://issues.dlang.org/show_bug.cgi?id=20567 and https://github.com/dlang/druntime/pull/2933