如果 async/await 只是线程的包装器,为什么 async/await 比线程执行得更好?

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

这个话题我想了很久。

假设我们有一个典型的 Web 服务器,一个在 Node.js 中,另一个在 Java 中(或任何其他具有线程的语言)。

为什么节点比 java 服务器性能更好(每秒处理更多基于 IO/network 的请求)只是因为它使用 async/await?它不只是一个使用相同线程的语法糖 java/c#/c++ 在幕后使用吗?

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

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

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

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

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

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

这里(到目前为止)的其他答案似乎都在解释 JS 中异步编程与 single-threaded 同步操作相比的好处——这是显而易见的,但不是问题所在。

每个人都同意的关键点是某些操作本来就很慢(例如:等待网络请求,等待 disk/database 访问),让 CPU 做其他事情效率更高而这些行动正在进行中。在您的应用程序中使用多个线程是一种 well-established 方法;但当然这只有在为您提供线程的语言中才有可能。许多传统的服务器实现(在 Java、C、C++ 中,...)每个请求使用一个线程(或者,等效地,一个线程池来分发传入的请求)。这些线程可以阻塞等待,比如说,数据库——没关系,操作系统会让等待线程休眠,同时让 CPU 在另一个线程上工作(处理另一个请求)。最终结果与您使用 Node 获得的结果非常相似。

Java当然,脚本不会为程序员提供线程。但相反,它具有使用 Java 脚本引擎调度请求并提供在请求完成时调用的回调的概念。这就是整个系统与传统线程编程语言类似的行为方式:用户代码可以说“做这件事,然后安排数据库访问,当结果可用时,继续这里的[回调]代码”,并在等待数据库请求,CPU 开始执行一些其他代码。您要避免的是 CPU 闲置等待,而其他工作正在等待 CPU 有时间处理它,这两种方法(Java 线程和 Java脚本回调)实现了这一点。

最后,async/await(就像 Promises 一样)确实只是语法糖,可以让编写 callback-based 代码变得更容易。使用 async/await 的代码并不比直接使用回调的 old-style 代码快,只是更漂亮和更少 error-prone。它也不比 (well-written) Java-based 服务器快。

Node.js 很受欢迎,因为在应用程序的客户端和服务器部分使用相同的语言很方便。从性能的角度来看,它 并不比传统替代方案好,它也 不差(或者至少不多;在实践中效率如何你设计你的应用程序比你是否在 Java 或 JavaScript 中实现它更重要。不要被炒作所迷惑:-)