June 10
On 6/6/2024 11:56 AM, Mathias Lang wrote:
> A resounding yes. Keeping the ability to easily bind to the CRuntime is useful (e.g. being able to spin up a socket and just look at the C documentation), but because it's "good enough", it was never good at all.

By CRT, I mean things like strlen, printf, and setting up the arguments for main(). Not sockets!
June 11
On Tuesday, 11 June 2024 at 00:01:01 UTC, Walter Bright wrote:
> On 6/8/2024 8:10 PM, Adam Wilson wrote:
>> [...]
>
> I don't understand how the CRT impedes any of that, or why any of it needs to be worked around. And D is intended to work with hybrid C/D code, so the CRT support needs to be there.
>
> The CRT also does some startup initialization things that need doing, like collecting the command line arguments to present to the program.

Why can't these things be in written D? Are we opposed to that or it's a matter of manpower (getting it done)?
June 11

On Sunday, 9 June 2024 at 16:58:33 UTC, Denis Feklushkin wrote:

>

On Saturday, 8 June 2024 at 21:15:39 UTC, monkyyy wrote:

As I remember, druntime uses not more than 10 CRT calls: allocate/free memory, sockets, threads. Thats all.

It upsets me that we have a huge core.stdc.* - it would be great to move these files somewhere

I don't know how many it is, but it's definitely more than 10, just the File I/O would be more than 10.

I agree that the system "DI" files do not belong in the Runtime and Rikki has proposed that we move all of the system API interface DI files out to a separate location. Maybe we could do something like windows.*, posix.*, macos.*, crt.*?

June 11

On Monday, 10 June 2024 at 09:36:14 UTC, Dmitry Olshansky wrote:

>

And on Posix libc is the systems API.

For some things yes, but if you want to do anything with Async I/O you're going to switch over to something like select or io_uring.

> >

Or kludges like Photon. (Don't get me wrong, Photon is a very cool piece of work, but the nature of it's implementation means that it suffers from the inherent limitations and drawbacks of fibers, and does so in a highly obfuscated way.)

I find critique of stackful coroutines really weak to be honest. Implementing n:m or 1:n threads is kernel doesn’t scale, but combining async io with user-space fibers works beautifully. The only problem I see is stack sizes, and even there we can just reserve a lot more on x64 it’s not a problem at all.

Java after all these years is putting lots of effort to support virtual threads, that would be introduced along side with normal threads.
Go is highly popular and doing just fine without even having normal threads.

That strikes me as more of an opinion than objective fact. I led a detailed discussion of this topic on Discord. The end result was that the stack size issue ends up being catastrophic in non-trivial workloads. Vibe went with a 16MB stack size for precisely this reason, which means that to handle 65536 simultaneous connections, I need a server with 1TB of RAM. The reason for that is that due to performance concerns, we turn off over-commit and thus allocating 16MB per stack means that you are fully committing 16MB of physical RAM. Go/Java/.NET, can all handle 10x that number of connections on a server with 128GB of RAM, so that's the bar we have to meet.

No other language suffers this problem, not even Go. The reason is that all languages that successfully use Fibers, use dynamically expanding stacks, but this means using a precise stack-scanning moving GC. Something that D, so long as Walter is among the living, will never have.

Stackless coroutines also do not suffer this problem, which is why .NET and Rust use them.

Here are some resources, including a real-world example from CloudFlare:
https://devblogs.microsoft.com/oldnewthing/20191011-00/?p=102989
https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p1364r0.pdf
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1520r0.pdf
https://blog.cloudflare.com/how-stacks-are-handled-in-go

>

On Windows I have no idea why we need to bind to libc at all. Synchronize with C’s io?

Beyond the fact that we currently use libc, I don't see any reason for us to either.

>

On Posix mostly syscall interface. That and malloc/free, memcpy/memset (simply because it’s optimized to death). All of the rest is legacy garbage no one is going to touch anyway.

And in the case of malloc/free, replacing those with different allocators has become quite the rage lately. jemalloc seems particularly popular. IIRC, Deadalnix's new GC uses a different allocator from libc. So even fewer reasons.

>

Being a system language D it allows anyone to use system APIs, meaning it’s easy to step on the toes of DRT if it uses lots of them.

Can you explain what you mean? I am not sure how we'd step on DRT's toes if applications use a lot of System API's?

June 11
On 11/06/2024 9:25 PM, Adam Wilson wrote:
> On Monday, 10 June 2024 at 09:36:14 UTC, Dmitry Olshansky wrote:
> 
>     And on Posix libc is the systems API.
> 
> For some things yes, but if you want to do anything with Async I/O you're going to switch over to something like |select| or |io_uring|.

Not select, that's the hello world of polling functions.

Right now Posix doesn't have anything for async, linux has epoll which can be the equivalent to IOCP.
June 11
On Tuesday, 11 June 2024 at 00:01:01 UTC, Walter Bright wrote:
> On 6/8/2024 8:10 PM, Adam Wilson wrote:
>> For example, let's say you want to do some asynchronous I/O. Forget the CRT, it just doesn't do that. So off you go to the system API's anyways. Or kludges like Photon. (Don't get me wrong, Photon is a very cool piece of work, but the nature of it's implementation means that it suffers from the inherent limitations and drawbacks of fibers, and does so in a highly obfuscated way.)
>
> I don't understand how the CRT impedes any of that, or why any of it needs to be worked around. And D is intended to work with hybrid C/D code, so the CRT support needs to be there.

Strictly speaking it doesn't "impede" it, but it does introduce multiple code-paths into the code. Let's say you want to do some Async File I/O. You simply can't in CRT because it's just not a thing that CRT does. Since you *have* to write code using the system interfaces to do this, you are going to write the System API path, so why not just use the System API path and cut out the middle-man?

I am not suggesting that we remove support for CRT from the language. Only that we build DRT such that it minimizes or completely removes it's use. We've also discussed a design where we continue to provide a CRT enabled version of DRT to make porting to new platforms easier, but would use the System API code paths by default on systems where those have been implemented. More work, because Phobos would have to be aware that you're using it and appropriately remove the code that CRT cannot support, but potentially worth it.

> The CRT also does some startup initialization things that need doing, like collecting the command line arguments to present to the program.

On Windows you use `CommandLineToArgvW`, on Linux/BSD's you might actually use the CRT, I don't know what the equivalent is on MacOS.
June 11

On Tuesday, 11 June 2024 at 00:03:29 UTC, Walter Bright wrote:

>

By CRT, I mean things like strlen, printf, and setting up the arguments for main(). Not sockets!

If anybody is using strlen in 2024 I will personally hunt them down and break every bone in their hands with a ball-peen hammer...

And one of these days we're going to need to have a conversation about printf...

June 11
On Tuesday, 11 June 2024 at 08:40:32 UTC, aberba wrote:
> Why can't these things be in written D? Are we opposed to that or it's a matter of manpower (getting it done)?

They can be done in D, and doing them in D would likely open us up to interesting use cases, like OSdev (since they no longer have to port CRT first), or acting as a bootstrap Runtime for modern languages that want to provide more than CRT.

However, we do have to be realistic about our manpower constraints. But if you're offering to lend a hand ... we'll take it!
June 11
On Tuesday, 11 June 2024 at 09:30:17 UTC, Richard (Rikki) Andrew Cattermole wrote:
> Not select, that's the hello world of polling functions.
>
> Right now Posix doesn't have anything for async, linux has epoll which can be the equivalent to IOCP.

Oh, I know. I was just working off you prior use of it as an example.

June 11

On Tuesday, 11 June 2024 at 09:25:15 UTC, Adam Wilson wrote:

>

On Monday, 10 June 2024 at 09:36:14 UTC, Dmitry Olshansky wrote:

>

And on Posix libc is the systems API.

For some things yes, but if you want to do anything with Async I/O you're going to switch over to something like select or io_uring.

Select is a system call so libc. io_uring is a system call with a dedicated library.

> > >

Or kludges like Photon. (Don't get me wrong, Photon is a very cool piece of work, but the nature of it's implementation means that it suffers from the inherent limitations and drawbacks of fibers, and does so in a highly obfuscated way.)

I find critique of stackful coroutines really weak to be honest. Implementing n:m or 1:n threads is kernel doesn’t scale, but combining async io with user-space fibers works beautifully. The only problem I see is stack sizes, and even there we can just reserve a lot more on x64 it’s not a problem at all.

Java after all these years is putting lots of effort to support virtual threads, that would be introduced along side with normal threads.
Go is highly popular and doing just fine without even having normal threads.

That strikes me as more of an opinion than objective fact. I led a detailed discussion of this topic on Discord. The end result was that the stack size issue ends up being catastrophic in non-trivial workloads. Vibe went with a 16MB stack size for precisely this reason, which means that to handle 65536 simultaneous connections, I need a server with 1TB of RAM.

Full stop right there. Virtual memory was designed precisely to handle cases like this, small allocations that may sometimes balloon to large in size. Reservation is not commit and detection of going out of range is quite possible on all OSes.

>

The reason for that is that due to performance concerns, we turn off over-commit and thus allocating 16MB per stack means that you are fully committing 16MB of physical RAM.

We can allocate virtual memory lazily even with overcommit disabled, in such a case you would use page fault handler to commit memory on as faulted basis.

>

Go/Java/.NET, can all handle 10x that number of connections on a server with 128GB of RAM, so that's the bar we have to meet.

No problem with reserving terabytes and using fraction of that. If the only problem is that you see memory as commited I’d be willing to look into why that is the case.

>

No other language suffers this problem, not even Go. The reason is that all languages that successfully use Fibers, use dynamically expanding stacks, but this means using a precise stack-scanning moving GC.

Far as I can tell Go dropped segmented stacks I cannot tell if they copy the stack around.

>

Something that D, so long as Walter is among the living, will never have.

Stackless coroutines also do not suffer this problem, which is why .NET and Rust use them.

The effort to introduce stackless coroutines together with rewriting the world to use them is enormous. The only reason behind Photon going as syscall wrapper is that we do not have resources to rewrite every C client library in say vibe.d sockets.

> >

Being a system language D it allows anyone to use system APIs, meaning it’s easy to step on the toes of DRT if it uses lots of them.

Can you explain what you mean? I am not sure how we'd step on DRT's toes if applications use a lot of System API's?

Easy - using the same signal number for something internal or segfault handler.


Dmitry Olshansky
CEO @ Glow labs
https://olshansky.me