Oh, my GoD! Goroutines on D

Jin nin-jin at ya.ru
Thu Jan 2 19:59:26 UTC 2025


>> received 100000000 messages in 2906 msec sum=4999999950000000 
>> speed=34411 msg/msec
>> so, it's ~2.7x faster than Java:
>> https://github.com/mingwugmail/liblfdsd/tree/master/comparison
>> And your https://github.com/nin-jin/go.d on my machine
>> go.d is 2~4 times slower than Go.
>> 9.7638ms (Go) v.s [19 ms ~ 40 ms] (go.d)

Hello everyone, I've done a little refactoring and optimization 
of [jin.go](https://github.com/nin-jin/go.d):
- I got rid of the vibe.d dependency because it's slow, big, and 
I haven't been able to make friends with version 2. When running 
only 1000 vibe-fibers, not only did the application crash, but 
even the graphics system driver crashed once, which required 
restarting the laptop.
- So far, I've settled on native streams with a small stack size 
(4 kb).
- I'm really looking forward to 
[photon's](https://github.com/nin-jin/go.d/issues/7) 
stabilization to get fiber support back. It would be really 
awesome to see it in the standard library.
- I had to abandon the move semantics because I couldn't make 
friends with the delegates. Currently, the number of references 
to the queue is controlled by the copy constructor.

Good news! After all the optimizations, the channels show 
impressive speed in the above benchmark for pumping messages 
between two streams.

```d
import std.datetime.stopwatch;
import std.range;
import std.stdio;

import jin.go;

const long n = 100_000_000;

     auto threadProducer() {
     	return n.iota;
     }

     void main() {
     	auto queue = go!threadProducer;

     	StopWatch sw;
     	sw.start();
     	long sum = 0;

     	foreach (p; queue) {
     		sum += p;
     	}

     	sw.stop();

     	writefln("received %d messages in %d msec sum=%d speed=%d 
msg/msec", n,
     		sw.peek.total!"msecs", sum, n / sw.peek.total!"msecs");

     	assert(sum == (n * (n - 1) / 2));
     }
     ```

```sh
received 100000000 messages in 718 msec sum=4999999950000000 
speed=139275 msg/msec
```

I've almost caught up with Go in [my goroutines 
benchmark](https://github.com/nin-jin/go.d/blob/master/compare.cmd):

```sh
> go run app.go --release
Workers Result          Time
8       49995000000     109.7644ms

> dub --quiet --build=release
Workers Result          Time
0       49995000000     124 ms
```

Bad news. Sometimes I get incorrect results and I can't figure 
out why.

```sh
> dub --quiet --build=release
Workers Result          Time
0       49945005000     176 ms
```

I use the atomic acquire and release operations, although they 
are not required on x86, but I hope the compiler takes them into 
account and does not reorder instructions. But even with stricter 
memory barriers, I don't get a very stable result. If someone can 
tell me what could be wrong here, I would be very grateful.


More information about the Digitalmars-d mailing list