August 13
On Wednesday, 13 August 2025 at 09:46:07 UTC, GL wrote:
> On Tuesday, 12 August 2025 at 14:14:04 UTC, Dmitry Olshansky wrote:
>> That would be something I could look into. I think it should be easily fixable. Do you have some examples that fail?
>
> Hello!
> Shure:
>
> import zmqd;
>
>    zmqd.Context context;
>    zmqd.Socket rec;
>
>    context = Context();
>    rec = Socket(context, SocketType.pull);
>
> ----------
>
> Invalid argument (src/poll.cpp:159)
> Error Program exited with code -6

Cool, so it dies on poll. Since poll is intercepted by photon, there is something I failed to account for. Let's see if I can get it fixed.
August 13
On Wednesday, 13 August 2025 at 10:08:17 UTC, Dmitry Olshansky wrote:
> On Wednesday, 13 August 2025 at 09:46:07 UTC, GL wrote:
>> On Tuesday, 12 August 2025 at 14:14:04 UTC, Dmitry Olshansky wrote:
>>> That would be something I could look into. I think it should be easily fixable. Do you have some examples that fail?
>>
>> Hello!
>> Shure:
>>
>> import zmqd;
>>
>>    zmqd.Context context;
>>    zmqd.Socket rec;
>>
>>    context = Context();
>>    rec = Socket(context, SocketType.pull);
>>
>> ----------
>>
>> Invalid argument (src/poll.cpp:159)
>> Error Program exited with code -6

So that was trivial mistake in handling -1 argument to poll.

Some more digging around and I've got the following to work:

import std.stdio;
import zmqd;
import photon;
import core.thread;

void main()
{
	startloop();
	shared bool terminated = false;
	go({
    	//  Socket to talk to clients
		auto responder = Socket(SocketType.rep);
		writeln("Got socket");
		responder.bind("tcp://*:5555");
		writeln("Binded socket");

		while (!terminated) {
			ubyte[10] buffer;
			responder.receive(buffer);
			writefln("Received: \"%s\"", cast(string)buffer);
			Thread.sleep(1.seconds);
			responder.send("World");
		}
	});
	go({
		writeln ("Connecting to hello world server...");
		auto requester = Socket(SocketType.req);
		requester.connect("tcp://localhost:5555");

		foreach (int requestNbr; 0..10)
		{
			ubyte[10] buffer;
			writefln("Sending Hello #%s", requestNbr);
			if (requestNbr == 9) terminated = true;
			requester.send("Hello");
			requester.receive(buffer);
			writefln("Received: %s #%s", cast(string)buffer, requestNbr);
		}
	});
	runFibers();
}

I need to think a little more about it but I would likely ship it in the next release. Soonish :)


August 16
On Wednesday, 13 August 2025 at 13:28:26 UTC, Dmitry Olshansky wrote:

> I need to think a little more about it but I would likely ship it in the next release. Soonish :)

Thank you!
I will wait with great impatience...
August 16
On Saturday, 16 August 2025 at 09:43:02 UTC, GL wrote:
> On Wednesday, 13 August 2025 at 13:28:26 UTC, Dmitry Olshansky wrote:
>
>> I need to think a little more about it but I would likely ship it in the next release. Soonish :)
>
> Thank you!
> I will wait with great impatience...

With new version v0.12.2 basic ZeroMQd example runs fine. Of other things HTTP server finally scales very well up to 48 cores and is faster than anything I've tried. (see photon-http 0.5.4)

https://github.com/DmitryOlshansky/photon/blob/master/tests/zmq.d

https://code.dlang.org/packages/photon

https://code.dlang.org/packages/photon-http

If you have more ZeroMQ code to test I'd gladly do it.

August 18
On Saturday, 16 August 2025 at 14:51:45 UTC, Dmitry Olshansky wrote:
> On Saturday, 16 August 2025 at 09:43:02 UTC, GL wrote:
>> On Wednesday, 13 August 2025 at 13:28:26 UTC, Dmitry Olshansky wrote:
>>
>>> I need to think a little more about it but I would likely ship it in the next release. Soonish :)
>>
>> Thank you!
>> I will wait with great impatience...
>
> With new version v0.12.2 basic ZeroMQd example runs fine. Of other things HTTP server finally scales very well up to 48 cores and is faster than anything I've tried. (see photon-http 0.5.4)

Actually that should be 0.5.5 :)

And v0.13.0 brings new feature - offload to run compute intensive tasks outside of scheduler. Certain syscalls are automatically routed through it to avoid blocking fibers such as file I/O. Here is simple example using goOnSameThread to make sure we are actually sharing just a single eventloop thread out of many and yet it doesn't block.

import photon;

double gauss(double a, double b, double function(double) f, double step) {
    double sum = 0.0;
    for (double x = a; x < b; x += step) {
        sum += (f(x+step) + f(x))/2 * step;
    }
    return sum;
}

void boom() {
    throw new Exception("Boom!");
}

long fib(long n) {
    if (n <= 2) return 1;
    else {
        return offload(() => fib(n-1)) + offload(() => fib(n-2));
    }
}

void main() {
    startloop();
    go({
        goOnSameThread({
            writeln("Blocking computation");
            writeln("Integral:", gauss(0.0, 10.0, x => x*x, 1e-7));
        });
        goOnSameThread({
            writeln("Blocking computation");
            writeln("Integral:", gauss(0.0, 10.0, x => x*x, 1e-7));
        });
        goOnSameThread({
            writeln("Nonblocking computation");
            writeln("Integral: ", offload(() => gauss(0.0, 10.0, x => x*x, 1e-7)));
        });
        goOnSameThread({
            writeln("Nonblocking computation");
            writeln("Integral: ", offload(() => gauss(0.0, 10.0, x => x*x, 1e-7)));
        });
        goOnSameThread({
            writeln("Catching exception from offloaded computation");
            try {
                offload(&boom);
                assert(0);
            } catch(Exception e) {
                assert(e.msg == "Boom!");
            }
        });
        goOnSameThread({
            writeln("Recursive offload");
            writeln("Fib(15):", offload(() => fib(15)));
        });
    });
    runFibers();
}

Other photon examples:
https://github.com/DmitryOlshansky/photon/tree/master



2 days ago
On Monday, 18 August 2025 at 15:20:14 UTC, Dmitry Olshansky wrote:
> On Saturday, 16 August 2025 at 14:51:45 UTC, Dmitry Olshansky wrote:
>> [...]
>
> Actually that should be 0.5.5 :)
>
> And v0.13.0 brings new feature - offload to run compute intensive tasks outside of scheduler. Certain syscalls are automatically routed through it to avoid blocking fibers such as file I/O. Here is simple example using goOnSameThread to make sure we are actually sharing just a single eventloop thread out of many and yet it doesn't block.
>
> import photon;
>
> double gauss(double a, double b, double function(double) f, double step) {
>     double sum = 0.0;
>     for (double x = a; x < b; x += step) {
>         sum += (f(x+step) + f(x))/2 * step;
>     }
>     return sum;
> }
>
> void boom() {
>     throw new Exception("Boom!");
> }
>
> long fib(long n) {
>     if (n <= 2) return 1;
>     else {
>         return offload(() => fib(n-1)) + offload(() => fib(n-2));
>     }
> }
>
> void main() {
>     startloop();
>     go({
>         goOnSameThread({
>             writeln("Blocking computation");
>             writeln("Integral:", gauss(0.0, 10.0, x => x*x, 1e-7));
>         });
>         goOnSameThread({
>             writeln("Blocking computation");
>             writeln("Integral:", gauss(0.0, 10.0, x => x*x, 1e-7));
>         });
>         goOnSameThread({
>             writeln("Nonblocking computation");
>             writeln("Integral: ", offload(() => gauss(0.0, 10.0, x => x*x, 1e-7)));
>         });
>         goOnSameThread({
>             writeln("Nonblocking computation");
>             writeln("Integral: ", offload(() => gauss(0.0, 10.0, x => x*x, 1e-7)));
>         });
>         goOnSameThread({
>             writeln("Catching exception from offloaded computation");
>             try {
>                 offload(&boom);
>                 assert(0);
>             } catch(Exception e) {
>                 assert(e.msg == "Boom!");
>             }
>         });
>         goOnSameThread({
>             writeln("Recursive offload");
>             writeln("Fib(15):", offload(() => fib(15)));
>         });
>     });
>     runFibers();
> }
>
> Other photon examples:
> https://github.com/DmitryOlshansky/photon/tree/master

I tried to include all the sources of photon in a application that it's cross-compiled to linux (Pi5, AArch64) and cross-linked with some C libs, and I'm seeing this:

```
2025-08-31T16:22:18.438 [error] extern(C) private ssize_t close(int fd) nothrow
src/photon/linux/core.d(1150,27):        Previous IR type: i32 (i32)
src/photon/linux/core.d(1150,27):        New IR type:      i64 (i32)
```

In linux.core.d: extern(C) private ssize_t close(int fd) nothrow

but `man 2 close` is `int close(int fd)`, it's a bug?





1 day ago

On Monday, 18 August 2025 at 15:20:14 UTC, Dmitry Olshansky wrote:

>
void main() {
    startloop();
    go({
        goOnSameThread({
            writeln("Blocking computation");
            writeln("Integral:", gauss(0.0, 10.0, x => x*x, 1e-7));
        });
    });
    runFibers();
}

One thing that I think could really be improved about Photon is these funny symbol names.

  • startloop is all-lowercase. It's two words so shouldn't it be startLoop?
  • go doesn't actually do any 'go-ing' right away, since fibres are deferred; so it's a little misleading. Maybe it could be more like schedule?
  • goOnSameThread is hyper-explicit compared to go, but its name still didn't help me understand it until I read the docs. Perhaps goSync or scheduleSync would be more intuitive?
  • runFiber is an unfortunate victim of the American-English disease. It would be nice to have an alias for 'fibre', which is the spelling used in the rest of the English-speaking world.

Would also be great to have a function named something like 'end loop' that cleans up everything that the library uses internally and allows Photon to be freshly re-initialised with startloop again later. This would be essential to using Photon in a modular environment. If Photon is no longer needed, then we don't want it hogging resources until the process dies. Obviously calling such a function should not work within a fibre.

1 2
Next ›   Last »