Hacker News new | ask | show | jobs
by jbirer 3103 days ago
I prefer golang's syscalls and os modules. Just direct interfaces to the C functions, no abstractions and no cruft.
9 comments

That's still an abstraction, just one built into the language. And Go's approach (as well as other things, like garbage collection) requires a runtime; while that does support an interesting programming model, it also makes Go unusable for a variety of use cases that need to run without a runtime.

This approach in Rust, as well as Rust's approach to memory management and other things, allow it to run without a runtime, which allows it to work for anything C does.

There's another reason Rust's ecosystem uses futures (as opposed to having some library-based greenthreading system): each future is like the stack of a userspace thread, but perfectly sized (it will be as large as the largest stack space needed at a yield point). This reduces the memory footprint of services using futures.
What use cases need no runtime (genuine question)? I understand the benefit of being compiled, since you can target a cpu instruction set and run without dependencies.
Low-level firmware, embedded applications, OS kernels, interrupt service routines, applications that can't afford the latency of being periodically interrupted, platforms where you don't have a scheduler or most OS services, libraries intended to be loaded into other applications written in other languages (e.g. where you don't control the main program entry point), writing language runtimes themselves, etc.

Early Rust, pre-1.0, did have a runtime and a green-threads mechanism; they ripped it out because they recognized that they couldn't go everywhere they wanted to go if they kept it. And if they hadn't done that, I believe Rust would have been far less successful than it has been.

So I'm guessing it's the runtime itself that expects to interact with things like an OS scheduler. Does that mean if you attempted to write an OS in Go, you'd basically have to do it without many of the features of the runtime (that provide the abstractions that are useful for application progamming?). That would be pretty crummy.
> Does that mean if you attempted to write an OS in Go, you'd basically have to do it without many of the features of the runtime (that provide the abstractions that are useful for application progamming?). That would be pretty crummy.

You'd have to write the lowest-level of it in a language that wasn't Go. That language could be C, or Rust, or a pseudo-Go that didn't have many of the features people expect (including garbage collection and goroutines).

Isn't go's greenthread offering part of it's runtime? If you use a go channel or thread, is that not calling some go std lib abstraction? What you're talking about seems like a pretty non-idiomatic use of go.
I'm not familiar enough with golang, but from your description it seems like in the Rust world, you're saying "I prefer the mio crate[1]"

[1] https://docs.rs/mio/0.6.10/mio/

AFAICT, a more go-like approach would be to use std::fs inside a std::thread
What's missing here is that Go has a userspace scheduler and greenthreads. Despite presenting the user with something that looks like old school blocking IO, because you are only blocking a greenthread it is actually asynchronous IO under the hood.

And of course there is a huge amount of abstraction to build this up. It's just all hidden in the language runtime, so people can say with a straight face that there is "no abstraction and no cruft."

Go's I/O is anything but a direct interface to the C functions. Its scheduler is a large abstraction.
For all asking what OP is talking about, this is example of using epoll directly in Go:

https://gist.github.com/tevino/3a4f4ec4ea9d0ca66d4f

This is description (from dotGo2017) of how netpoll works in Go under the hood if anyone is interested:

https://www.youtube.com/watch?v=xwlo3xigknI

I am not sure what exactly that gist tries to show. As it forces the go runtime to run each read call on a separated native thread, it just shows that one can use go to implement rather bad epoll antipattern.
My understanding is that Go programs typically tackle these problems with goroutines and channels which are definitely an abstraction over kernel functionality.
Does golang use io completion on Windows? I know Tokio does so if that's not the case then there's probably a pretty large delta in performance.
That's not idiomatic Go, is it? Go also abstracts I/O by converting it to async under the hood.
Go IO is implemented with green threads using a scheduler underneath.

Rust had green threading in the initial phases but this was voted out.