Live data from Hacker News

Async might be a fad

cs.oswego.edu

51–60 of 76 posts

Re: Async might be a fad

#51
I don't write web applications, and I don't use much JavaScript, so it's very possible that I don't properly understand the motivation for this blog post. However, as others have said there is a difference between some inconvenient syntax in JS, and the fundamental model of non-blocking I/O.

What I do write is lots of C/C++ client/server applications for HPC/HFT/DC workloads where speed both in req/sec (throughput) and speed in min/avg/max(secs/req) (latency) matters. In these environments I almost exclusively use non-blocking I/O. There are several reasons:

1) Threads are not free. Even if you use a thread-pool to avoid spin up costs, context switching overhead matters. Every time you call blocking I/O, you make sure that the kernel will wake up, schedule another thread, and do anything else that it decides to do. Waste time that you could have used to do useful work. Non-blocking I/O puts you in charge of your own "thread scheduler". Your "threads" are functions, they are "cooperatively scheduled" and you can make full use of every cycle that you get.

2) Programming with threads is hard. Trust me. If you think it's easy, or I'm soft, you haven't done it enough. At some point you will need shared state across those threads. And then you'll need locking and unlocking. (also Mutexs are slooooowww) And then you'll need to handle error cases, and you'll need to make sure that all the unlocking is done right in all of the right places. And then you'll need signaling between your threads. And you'll need semaphores or similar. And 3 months down the line, you're thinking to yourself, when a foo exception causes a bar signal, will a baz handler deadlock? Will it make progress? Humans just aren't designed to reason about this sort of thing.

With a single threaded, non-blocking design, it's really easy to reason about exactly what is happening with all of your state. Debugging is obvious and straightforward. This is necessary if you're like me and don't write perfect code first time. There's only ever one function accessing shared state at one time. The "scheduler" is working for you, not against you. If you write your code simply, cleanly and efficiently, you'd be amazed how much work a modern CPU can really do. Honestly, once you've saturated a 10G NIC what more do you want to do?

3) If you buy into the non-blocking design, then, as long as you only use 1 process/thread per core, almost anything a thread can do, a process can do better. Threads have no memory protection, anything you touch probably belongs to some other thread and you're inviting subtle bugs. Processes have memory protection by default if you want to share things you can do it explicitly via safe mechanisms (shared memory rings, pipes, IPC etc). Shared memory rings are (can be) so fast that data is more or less local so if you want to use shared state from a TCP connection or whatever, you can always "dispatch" work to another process to do it for you. You get the benefits of many cores working for you as well as a clean and obvious programming model.

Ultimately, if the question is one of syntax, then I'd happily believe that JS has some ugly syntax for doing these things, but if the question is one of design, then you should think really really hard before deciding that a threaded model is the correct one for you.

Re: Async might be a fad

#52

I don't write web applications, and I don't use much JavaScript, so it's very possible that I don't properly understand the motivation for this blog post. However, as others have said there is a difference between some inconvenient syntax in JS, and the fundamental model of non-blocking I/O. What I do write is lots of C/C++ client/server applications for HPC/HFT/DC workloads where speed both in req/sec (throughput) a…

Of course it all depends upon the application. Processes are very heavy weight constructs. If you have a variable number of low-latency or lengthy tasks to do (streaming media, data reformatting, responding to external events) then threads are a good fit.

Encapsulation is your friends. If each thread deals with a non-overlapping (set of) object(s), then many of the issues are gone. What is left is messaging between a thread and the process, which can be done using a thread-safe queue.

Re: Async might be a fad

#53
post #5

Async computation is not the fad, it's poor syntax is. C#, F# and coffeescript have excellent syntax that remove the line noise caused by writing async code. Actors and channels also nicely remove line noise from async programming. If anything as computers become more powerful and distributed you'll see threads and locks disappear rather than async computation. Async computation in an imperative style is what most wa…

That is where I disagree completely. I think the old fashioned sync/blocking/threaded style is much easier than async. Of course, C# has great async support; but it is still a complicate thing that programmers must be very cautious about when applying.

I don't think you've seen truly great async support, it's virtually indistinguishable from sync code.

Sync:

  let file = File.Open("foo.txt")
  let data = file.Read(8192)
  // Do some compute stuff with data
ASync:

  let! file = File.OpenAsync("foo.txt")
  let! data = file.ReadAsync(8192)  
  // Do some compute stuff with data

Re: Async might be a fad

#54

Earlier quoted context omitted.

That's a matter of terminology. I don't call `go` "async".

How do you define "async" that excludes Go?

I use the word from the programmer's point of view; it's irrelevant how things are done under the hood.

For example, in Go, when you read a value from a channel, it's just like a good old blocking call, as far as the programmer is concerned.

On the other hand, an "async" read would involve callback, promise, or some other constructs.

Re: Async might be a fad

#55

I don't write web applications, and I don't use much JavaScript, so it's very possible that I don't properly understand the motivation for this blog post. However, as others have said there is a difference between some inconvenient syntax in JS, and the fundamental model of non-blocking I/O. What I do write is lots of C/C++ client/server applications for HPC/HFT/DC workloads where speed both in req/sec (throughput) a…

Of course it all depends upon the application. Processes are very heavy weight constructs. If you have a variable number of low-latency or lengthy tasks to do (streaming media, data reformatting, responding to external events) then threads are a good fit. Encapsulation is your friends. If each thread deals with a non-overlapping (set of) object(s), then many of the issues are gone. What is left is messaging between a…

Hmm. I don't think I made myself very clear. I failed to mention that I'm advocating 1 process per core, not hundreds (thousands) of processes. Over subscribing processes to cores has the same effect of oversubscribing threads to cores, which is suboptimal scheduling. Furthermore, this model allows you to easily pin work to cores (using process affinity) and to get all the juicy benefits of using cooperative scheduling inside your processes.

I think the view that processes are "heavy weight" is a dated one. From an OS point of view, processes are pretty much the same amount of "work" as thread. Each has a context, each needs to be scheduled. Processes do have some extra state (notably the TLB context) but modern machines are very good switching these. Spinning up processes is somewhat more expensive than spinning up threads, but you really shouldn't be doing either on the critical path.

I agree that everything is context specific, although my main application area is really low latency scenarios (handfuls of microseconds) and techniques that work well there tend to port well to slower situations pretty easily (at least in my experience).

I disagree that encapsulation and non-overlapping objects will save you from threading nightmares. Every design starts out with clean boundaries and beautiful abstractions. Every design ends up in spaghetti soup. It's just a matter of how long it takes to get there.

Re: Async might be a fad

#56
post #53

Earlier quoted context omitted.

That is where I disagree completely. I think the old fashioned sync/blocking/threaded style is much easier than async. Of course, C# has great async support; but it is still a complicate thing that programmers must be very cautious about when applying.

I don't think you've seen truly great async support, it's virtually indistinguishable from sync code. Sync: let file = File.Open("foo.txt") let data = file.Read(8192) // Do some compute stuff with data ASync: let! file = File.OpenAsync("foo.txt") let! data = file.ReadAsync(8192) // Do some compute stuff with data

while the syntax can be as simple as that, there is still a difference, and the programmer still needs to be very careful. what if you accidentally forget the `"!"`?

Re: Async might be a fad

#57

I don't write web applications, and I don't use much JavaScript, so it's very possible that I don't properly understand the motivation for this blog post. However, as others have said there is a difference between some inconvenient syntax in JS, and the fundamental model of non-blocking I/O. What I do write is lots of C/C++ client/server applications for HPC/HFT/DC workloads where speed both in req/sec (throughput) a…

I apologize for the sensational and generalizing title. What I'm talking about is focused on web applications, and from empirical data, it seems that most web servers handle very few concurrent requests, therefore it would be silly to go all async to avoid threads.

I'm very surprised that many people here argue that async code is much better to understand than sync code. Ok, so that part is subjective, and let's file it under personal preference. For people who love synchronous coding but fear the cost of threads, I'm trying to make an argument that the fear is probably not justified.

Re: Async might be a fad

#58
post #13

Earlier quoted context omitted.

Maybe I'm looking at this from a different perspective. Some implementations do not require any response. For example if I have a honey pot that collects random events, the clients can just send the data to it without expecting a result (IE: I don't care if it's successful or not) and honey pot is not expected to write any sort of response. Clients send data and move on.

I agree, async is needed sometimes. Another example, a server broadcasts an event to multiple clients (e.g. a chat app), it would be silly to spawn a thread per client for that.

But the whole point of async is that, after data is dispatched the client moves on. I'm not sure what NodeJS does with it but this is my interpretation of the concept.

I don't think people who know what they are doing, use async calls for mission critical operations.

If async call returns response and client is required to read the response it's no longer considered non-blocking from technical perspective.

Re: Async might be a fad

#59

I don't write web applications, and I don't use much JavaScript, so it's very possible that I don't properly understand the motivation for this blog post. However, as others have said there is a difference between some inconvenient syntax in JS, and the fundamental model of non-blocking I/O. What I do write is lots of C/C++ client/server applications for HPC/HFT/DC workloads where speed both in req/sec (throughput) a…

I apologize for the sensational and generalizing title. What I'm talking about is focused on web applications, and from empirical data, it seems that most web servers handle very few concurrent requests, therefore it would be silly to go all async to avoid threads. I'm very surprised that many people here argue that async code is much better to understand than sync code. Ok, so that part is subjective, and let's file…

Thanks for the very considered response. I'm pretty interested in this because some of my recent work has been about designing I/O APIs/abstractions.

My reaction is due to my experience which is that threaded programming is something that's very hard to get right and especially to maintain. Async programming cleans up the threading and makes it kind of implicitly cooperative.

I was involved in a big move of some core infrastructure from a multi-threaded design over to a pipeline of async style apps. The result was a huge boost in productivity and debugability which worked out really well for the company.

Re: Async might be a fad

#60

The select() loop has been a core part of unix since before many people here were born. That's the basis of async, evented IO—it's hard to call that a fad. Perhaps the callback mechanism of Node is a fad—continuation based techniques can make async code look like non-async code. Perl's Coro and Ruby's new(ish) fibers are examples of how that could look.

what I meant is whether it's a fad to spread async everywhere inside application code, and call that a good thing. the computer is of course async in nature; but the abstraction on the app layer does not have to be.

> the computer is of course async in nature; but the abstraction on the app layer does not have to be.

Aren't computers actually synchronous? The abstraction on the OS layer is what makes computers async.

At the programming-language layer, async means you can write programs based on how the user and your program interact with each other. Other applications (and the OS itself) behave asynchronously too. Why make it harder?

Of course it shouldn't have to be that way (it didn't use to be), but it's very convenient to think around "what is actually happening" instead of "what the synchronous execution of the program is doing".

EDIT: but now I've seen you only meant a specific subset of async. I'm leaving the comment here anyways.

Post reply on HN