Live data from Hacker News

Asynchronous IO in Rust

medium.com

71–80 of 111 posts

Re: Asynchronous IO in Rust

#72
post #45

Earlier quoted context omitted.

The dynamically-allocating portions of the stdlib may panic on OOM, but in an embedded context you're not even linking that code into your program. And you're free to provide an alternative stdlib that bubbles up OOM for those rare occasions where you want to dynamically allocate and you want to be able to do something sane in the face of OOM and you're on a platform that doesn't overcommit.

OOM is an abort, not a panic (contrary to the official docs, interestingly) > you're free to provide an alternative stdlib But like... should you have to? > for those rare occasions In kernel programming, allocation failures are common and handling them is essential. To quote my (very talented) classmate, who actually wrote part of a kernel in Rust: "The only really major issue is with how allocation failure works, w…

  > OOM is an abort, not a panic (contrary to the official docs, interestingly)
Where in the docs do we say this? I'd like to fix it.

Re: Asynchronous IO in Rust

#73
post #56

Earlier quoted context omitted.

No, backwards: the C10k techniques are the solution to the problem "how do I achieve my performance and scaling goals given the characteristics of the OS, languages, tools available to me today?". The current thread (sic) is asking the question "if we can change the language, tools (perhaps the OS too), what's the best approach?". And: I have to counterbalance the assertion that Node.js is in any way good for anythin…

That's exactly the point. So my question remains: if threads are the right answer today, either the C10K folks were wrong or something has changed since then. What?

The question is a different question, hence the answer is different. C10k wasn't considering the option of new languages, this thread is. The same question could have been asked back then (although most folks wouldn't have considered using anything other than C/C++ for high-scale servers then). Perhaps the thing that's changed is more memory and CPU power has made the option of new (and less efficient than C) languages a practical choice for new projects. I know that if, back then, I'd proposed the solution to my product's scaling issues with network I/O to be : "re-write all 500k loc in a different language", I'd have been laughed at.

Re: Asynchronous IO in Rust

#74
post #40

I think a lot of folks think of Network IO when they say Asynchronous IO. That's only half the story, unless you're just building proxies and caches you have to deal with Disk IO at some point in time. And, async disk IO is horrible in every OS / language.

Well, apparently not on Windows. But this is a kernel interface issue not a language issue, and clearly needs fixing now we have SSDs where having thousands of outstanding requests is useful, if not required for performance, unless the hardware APIs are going to change (maybe if they get memory interfaces this does change).

The async story on windows is better, but not great. In many cases the async calls on windows silently block due to a number of special cases (that are not so special).

Re: Asynchronous IO in Rust

#75

Earlier quoted context omitted.

This is backwards. Green threading can be an implementation detail, but in languages where it's a key feature, green threads let you write code that would otherwise be incorrect. For example, in a native threading model, it is an awful idea to spawn a thread for every incoming connection on a server. It's the easy way to write it, but it's wrong. With a green threading model, though, that's easy and efficient.

> For example, in a native threading model, it is an awful idea to spawn a thread for every incoming connection on a server. It's the easy way to write it, but it's wrong. With a green threading model, though, that's easy and efficient. A thread per connection isn't wrong, though. You're begging the question by assuming that green threads are faster than native threads. I'm specifically arguing against that.

As I already said, green threads are not faster than native threads. That makes no sense. Green threads, due to smaller stacks and cheaper context switches, are more scalable and predictable at the cost of extra user land bookkeeping.

Re: Asynchronous IO in Rust

#76

Earlier quoted context omitted.

> For example, in a native threading model, it is an awful idea to spawn a thread for every incoming connection on a server. It's the easy way to write it, but it's wrong. With a green threading model, though, that's easy and efficient. A thread per connection isn't wrong, though. You're begging the question by assuming that green threads are faster than native threads. I'm specifically arguing against that.

As I already said, green threads are not faster than native threads. That makes no sense. Green threads, due to smaller stacks and cheaper context switches, are more scalable and predictable at the cost of extra user land bookkeeping.

The point is: who cares? Do you really need 3 million threads (particularly, 3 million threads that aren't as efficient as ordinary threads for many tasks)? Ostensibly Google does about 3 billion queries a day; that's less than 35,000 queries per second. Obviously, there are many services underlying any Google search, but most of them will be distributed among multiple cores, machines, and datacenters. So what eventuality are you preparing for where regular threads won't be sufficient?

Re: Asynchronous IO in Rust

#77

Earlier quoted context omitted.

I'm confused. To me, green threads are just an implementation detail. The fact that green threading is being used shouldn't leak into the interface. To take Go for an example, you could perfectly well write a conforming implementation of Go that used 1:1 native threading: it would just have different performance characteristics and things like LockOSThread() would become a no-op. Could you elaborate on what you consi…

The interface is different because if you use a green thread within a GC'd language, you can do anything -- change anything, interact with anything -- and nothing will crash. No locking involved, and no hidden locking under the hood. It's not meant to be a performance boost, but a way of writing code where "might this crash?" is a question you're never bothered to ask. It's wonderfully freeing. Not true of native thr…

> a way of writing code where "might this crash?" is a question you're never bothered to ask.

Is that actually true? Yes, you won't get a partially written int, but you could still run into consistency issues if you don't lock. For example, if you need thread A to update both x and y to have a consistent state, and B is reading both x and y, A might update x, then the scheduler would switch to B, and be might read the new x and the old y. If the update A was making needed to update both x and y for the system to be in a consistent state, you have a problem.

Re: Asynchronous IO in Rust

#78
post #67

Earlier quoted context omitted.

This is backwards. Green threading can be an implementation detail, but in languages where it's a key feature, green threads let you write code that would otherwise be incorrect. For example, in a native threading model, it is an awful idea to spawn a thread for every incoming connection on a server. It's the easy way to write it, but it's wrong. With a green threading model, though, that's easy and efficient.

I was curious what the actual state was of the "modern Linux kernel" pcwalton mentioned, so I tried running a test program to create a million threads on a VM - x86-64 with 8GB of RAM, Linux 4.0. For comparison, Go apparently uses about 4KB per goroutine, so it should be possible to create somewhat under 2 million goroutines. To be fair, I allocated the stacks manually in one large allocation; otherwise it dies quite…

> To be fair, I allocated the stacks manually in one large allocation; otherwise it dies quite quickly running out of VM mappings.

Okay, so the test you did doesn't actually reflect the use case in practice. Can I expect to reach 200,000 threads if the threads are not all created at exactly the same moment? What if (God forbid) they're doing memory allocation? And if it does work out, will everything be handled efficiently?

Re: Asynchronous IO in Rust

#79

Earlier quoted context omitted.

As I already said, green threads are not faster than native threads. That makes no sense. Green threads, due to smaller stacks and cheaper context switches, are more scalable and predictable at the cost of extra user land bookkeeping.

The point is: who cares? Do you really need 3 million threads (particularly, 3 million threads that aren't as efficient as ordinary threads for many tasks)? Ostensibly Google does about 3 billion queries a day; that's less than 35,000 queries per second. Obviously, there are many services underlying any Google search, but most of them will be distributed among multiple cores, machines, and datacenters. So what eventu…

The point isn't that I need 3 million threads. The point is that I can easily write code that is correct and behaves predictably even if I end up throwing some arbitrary number of threads at the processor.

As I view them, green threads are a useful abstraction just like objects or functions. Do you need something computed, not necessarily now, but at some point? Just make a green thread to compute it and check on the result later. That's the platonic ideal of green threads, anyway: very few languages have gotten to that point (Erlang, maybe Go, on a good day; C# has this with its async functionality but none of it happens in parallel).

Re: Asynchronous IO in Rust

#80
post #67

Earlier quoted context omitted.

This is backwards. Green threading can be an implementation detail, but in languages where it's a key feature, green threads let you write code that would otherwise be incorrect. For example, in a native threading model, it is an awful idea to spawn a thread for every incoming connection on a server. It's the easy way to write it, but it's wrong. With a green threading model, though, that's easy and efficient.

I was curious what the actual state was of the "modern Linux kernel" pcwalton mentioned, so I tried running a test program to create a million threads on a VM - x86-64 with 8GB of RAM, Linux 4.0. For comparison, Go apparently uses about 4KB per goroutine, so it should be possible to create somewhat under 2 million goroutines. To be fair, I allocated the stacks manually in one large allocation; otherwise it dies quite…

It would be interesting to run the same test using musl, which allows a smaller minimum stack size.
Post reply on HN