为什么异步/等待比线程表现更好,即使它只是对线程的封装?

huangapple go评论84阅读模式
英文:

Why async/await performs better than threads if it is just a wrapper around them?

问题

这个话题在我心中已经很久了。

假设我们有一个典型的网络服务器,一个使用Node.js,另一个使用Java(或者任何其他带有线程的编程语言)。

为什么 Node 表现会更好(每秒处理更多基于 IO/网络的请求),仅仅因为它使用了异步/等待(async/await)呢?难道它不只是一种语法糖,实际上背后也利用了类似于Java/C#/C++中使用的线程吗?

英文:

This topic was on my mind for a long time.

Let's assume we have a typical web server, one in Node.js and the other in Java(or any other language with threads).

Why would node perform better (handle more IO/network based requests per second) than a java server just because it uses async/await? Isn't it just a syntatic sugar that utilizes the same threads java/c#/c++ use behind the scenes?

答案1

得分: 4

没有理由期望 Node 比用 Java 编写的服务器更快。你为什么认为会呢?

看起来这里的其他答案(到目前为止)正在解释 JS 中异步编程相对于单线程同步操作的优势 —— 这是显而易见的,但不是问题的重点。

每个人都同意的关键点是,某些操作本质上是缓慢的(例如:等待网络请求,等待磁盘/数据库访问),在这些操作正在进行时,让 CPU 在后台执行其他任务是高效的。在应用程序中使用多个线程是一种既定的方法;当然,这只在那些提供线程的语言中才可能。许多传统的服务器实现(如 Java、C、C++ 等)每个请求使用一个线程(或等价地,使用线程池分发传入的请求)。这些线程可能会阻塞,等待数据库的响应 —— 这没关系,操作系统会让等待中的线程休眠,同时让 CPU 在另一个线程上工作(处理另一个请求)。最终的结果与使用 Node 得到的结果相当。

当然,JavaScript 并没有为程序员提供线程。但它有一种将请求安排到 JavaScript 引擎中并提供回调以在请求完成时调用的概念。这就是整个系统的行为类似于传统的线程编程语言的方式:用户代码可以说“做这些事情,然后安排一个数据库访问,在结果可用时继续执行这里的[回调]代码”,而在等待数据库请求时,CPU 可以执行一些其他代码。你要避免的是 CPU 闲着无所事事,而有其他工作在等待 CPU 有时间来处理,Java 线程和 JavaScript 回调这两种方法都实现了这一点。

最后,async/await(就像 Promises 一样)实际上只是让编写基于回调的代码更加方便的语法糖。使用 async/await 的代码并不比直接使用回调的老式代码更快,只是更漂亮且更少出错。它也不比(写得好的)基于 Java 的服务器更快。

Node.js 之所以受欢迎,是因为在应用程序的客户端和服务器部分使用相同的语言非常方便。从性能的角度来看,它并不比传统的替代方案更好,只是也并不更差(或者至少差别不大;在实际中,你如何高效地设计应用程序比你是用 Java 还是 JavaScript 来实现更重要)。不要被炒作所迷惑 为什么异步/等待比线程表现更好,即使它只是对线程的封装?

英文:

There is no reason to expect Node to be faster than a server written in Java. Why do you think it might be?

It seems the other answers here (so far) are explaining the benefits of asynchronous programming in JS compared to single-threaded synchronous operations -- that's obvious, but not the question.

The key point everyone agrees on is that certain operations are inherently slow (e.g.: waiting for network requests, waiting for disk/database access), and it's efficient to let the CPU do something else while such operations are in flight. Using several threads in your application is one well-established way to do that; but of course that's only possible in languages that give you threads. Many traditional server implementations (in Java, C, C++, ...) use one thread per request (or, equivalently, a thread pool to distribute incoming requests over). These threads can block waiting for, say, the database -- that's okay, the operating system will put the waiting thread to sleep and let the CPU work on another thread (handling another request) in the meantime. The end result is fairly similar to what you get with Node.

JavaScript, of course, doesn't make threads available to the programmer. But instead, it has this concept of scheduling requests with the JavaScript engine and providing a callback to be invoked upon completion of the request. That's how the overall system behaves similarly to a traditional threaded programming language: user code can say "do this stuff, then schedule a database access, and when the result is available, continue with this [callback] code here", and while waiting for the database request, the CPU gets to execute some other code. What you want to avoid is the CPU sitting around idly waiting while there is other work waiting for the CPU to have time for it, and both approaches (Java threads and JavaScript callbacks) accomplish that.

Finally, async/await (just like Promises) are indeed just syntactic sugar that make it easier to write callback-based code. Code using async/await isn't any faster than old-style code using callbacks directly, just prettier and less error-prone. It also isn't any faster than a (well-written) Java-based server.

Node.js is popular because it's convenient to use the same language for the client and server parts of an app. From a performance point of view, it's not better than traditional alternatives, it's just also not worse (or at least not much; in practice how efficiently you design your app matters more than whether you implement it in Java or JavaScript). Don't fall for the hype 为什么异步/等待比线程表现更好,即使它只是对线程的封装?

答案2

得分: 0

异步编程(asyn/await)对于那些可能会阻塞的活动是至关重要的,比如当你的应用程序访问网络时。访问网络资源有时会很慢或延迟。如果这样的活动在同步过程中被阻塞,整个应用程序必须等待。

在异步进程(线程)中,应用程序可以继续进行其他不依赖于网络资源的工作,直到可能会阻塞的任务完成。

https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/hh191443(v=vs.110)?redirectedfrom=MSDN#threads 尽管你应该理解线程和异步/await编程之间的区别。

英文:

Asynchrony(asyn/await) is essential for activities that are potentially blocking, such as when your application accesses the web. Access to a web resource sometimes is slow or delayed. If such an activity is blocked within a synchronous process, the entire application must wait.

In an asynchronous process (thread), the application can continue with other work that doesn't depend on the web resource until the potentially blocking task finishes.

https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/hh191443(v=vs.110)?redirectedfrom=MSDN#threads Though you should understand the differences between threads and async/await programming.

答案3

得分: 0

关于异步编程,可用性是关键。例如,一个请求可以分成多个较小的任务,即获取内部结果、读取、写入、建立连接等等... 因此,有一半的时间会浪费在等待依赖任务上。异步模型利用这段时间处理其他传入的请求,保持回调函数,注册在队列中保存状态,并变为可用于另一个请求。因此,它们可以处理更多的请求。

了解有关处理请求的更多信息:https://www.youtube.com/watch?v=cCOL7MC4Pl0

英文:

In regards to Asynchronous programming, Usability is the key. For instance, one request can be split up into smaller tasks i.e. fetching into internal results, reading, writing, establishing connections etc... thus, half the time gets wasted waiting on dependent tasks. Asynchronous models use this time to handle other incoming requests keeping a callback function, registering in a queue saving the state and becomes available for another request. Thus, they can handle more requests.

Understand more on handling requests: https://www.youtube.com/watch?v=cCOL7MC4Pl0

huangapple
  • 本文由 发表于 2020年8月16日 17:12:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/63435094.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定