首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >创建比可用处理器更多的线程会有性能开销吗?

创建比可用处理器更多的线程会有性能开销吗?
EN

Stack Overflow用户
提问于 2021-08-16 00:16:32
回答 1查看 212关注 0票数 1

我的目标是处理线程内部的WebSocket连接。如果我使用in a new Thread,服务器可以处理的WebSocket连接的数量是未知的。如果我使用in a Thread pool,服务器可以处理的WebSocket连接的数量就是线程池大小。

我不确定可用处理器和线程之间的相关性。一个处理器一次执行一个线程吗?

我的预期结果是:创建比可用处理器更多的线程是不可取的,您应该重新设计如何处理WebSocket连接。

在一个新的线程中

代码语言:javascript
运行
复制
final Socket socket = serverSocket.accept();

new Thread(new WebSocket(socket, listener)).start();

在线程池中

代码语言:javascript
运行
复制
final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

final Socket socket = serverSocket.accept();

es.execute(new WebSocket(socket, listener));

为了避免混淆,WebSocket类是实现Runnable的自定义类。据我所知,Java没有WebSocket服务器,只有WebSocket客户机。

EN

Stack Overflow用户

回答已采纳

发布于 2021-08-16 01:26:17

做线。一千,如果你愿意的话。

在CPU核心级别,下面是正在发生的事情:

  • CPU核心在前进,为给定的websocket工作。
  • 很快,内核就遇到了一个路障:一半的传入数据已经到达,其余的数据仍在网络电缆上运行,因此CPU在到达之前无法继续工作。或者,CPU核心正在运行的代码正在发送数据,但是网卡的缓冲区已经满了,所以现在CPU核心必须等待该网卡找到方法,在电缆上发送另一个数据包,然后才有空间。
  • 当然,如果有工作要做(比方说,你的盒子里有10个核心,同时连接着15个网络用户,那么现在至少有5个网站用户在等着)--那么应该是,而不是,只是开始摆弄它的拇指。它应该做点什么。
  • 那么,在实践中,有一整船的内存是相关的,但现在已经不再相关了(所有包含所有状态和其他“工作项”的内存都必须为我们正在处理的websocket完成工作,但它目前正在被网络“阻塞”),还有一整堆与此无关的内存(之前放入的websocket连接的所有状态和工作内存“有一点超时,等待网络数据包到达”)--网络数据包已经到达了。因此,如果一个CPU核心可以自由工作,那么它现在可以开始工作了)。
  • 这被称为“上下文切换”,它是非常昂贵的,500+周期值。这也是完全不可避免的。您必须使上下文切换。你不能逃避它。这意味着要付出一定的代价,大约有500个周期值得你去厕所。这就是它是什么。

问题是,有两种方式可以支付这一费用:您可以切换到另一个线程,这是各种上下文切换。或者,您有一个线程运行所谓的‘异步’代码,它自己管理所有这些东西,然后跳到另一个工作中去,但是仍然有一个上下文开关。

具体来说,CPU现在再也不能与内存进行交互了,过去十年也没有了。它们只能与CPU缓存页交互。实际上,机器代码不再是真正的“直接运行”了,相反,在CPU注意到它即将运行一条涉及到某些内存的指令之后,它会将内存命令(毕竟,CPU不能再与它交互)映射到缓存中的正确位置。它还会注意到,如果您试图用机器代码访问的内存根本不在与该核心相关联的缓存页中,在这种情况下,它将触发一个缺页中断,从而导致CPU /内存总线的内存子系统“退出一个页”(将所有内存写回主内存),然后加载到正确的页中,然后CPU才会继续运行。

这一切都发生在“引擎盖下”,您不必编写代码来切换页面,而是由CPU自动管理它。但这是一个沉重的代价。不像线程开关那么重,但几乎和线程开关一样重。

结论:线程很好,有很多线程。它确保CPU在有工作要做的时候不会手忙脚乱。请注意,有许多博客文章赞美异步的优点,声称线程“不缩放”。他们错了。线程扩展得很好,异步代码也一直在支付上下文切换的费用。。

如果您没有意识到,“异步代码”是一种尝试永不休眠的代码(永远不要做一些等待的事情。因此,您不必编写'getMeTheNextBlockOfBytesFromTheNetworkCard',而是编写:“onceBytesAreAvailableRunThis(代码转到这里)”。用java编写异步代码是可能的,但与使用线程相比非常困难。

即使在非常罕见的情况下,异步代码将是一个重大的胜利,Project已经接近完成,这将使java能够拥有您可以手动管理的类似线程的东西(所谓的纤维)。这就是OpenJDK为此选择的路线。在这个意义上,即使你认为异步是答案,不,它不是。等待项目织机完成,相反。如果您想阅读更多内容,请阅读你的功能是什么颜色的?回调地狱。这两篇文章都不是特定于java的,而是涵盖了异步中固有的一些更严重的问题。

票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68796254

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档