背景
我们有一个在网络浏览器中播放的快节奏多人在线游戏。通过安全WebSocket,客户端可以连接到GameServer并在某些情况下每秒发送约60个数据包。我们注意到,当客户端通过WebSocket向GameServer发送任何请求时,即使GameServer除了库的网络捕获功能之外没有执行任何逻辑,我们的GameServer的CPU性能也非常糟糕。包。您可能会怀疑,更多请求会产生更高的CPU使用率。多么糟糕?好吧,我们已经看到大约30%的CPU使用率仅用于少数几个请求。有时它浮动在3%左右,但是对我(不是线程专家)来说,当我们只是对所使用的线程感到幸运时,就会发生这种情况。
GameServer代码在Quad Core hosted by Linode上运行。
有问题的GameServer WebSocket库是TooTallNate Java-WebSocket。
复制和分析
运行jvmtop --profile
会产生以下结果https://i.gyazo.com/6419081e6254cd82aec52eb451f24bd9.mp4(最大化并斜视以读取数据)。您会看到它达到了〜90%,将可疑者指向WebSocketServer.run()。我们注意到在发生gc时,还会有更多的CPU命中,但是您可以看到在此之前发生了加速。
The jstack
provided further insights。 (我们使用的是Java-WebSocket的主版本,但是由于添加了一些调试语句,因此某些代码行可能会略有偏离)。我们怀疑LinkedBlockingQueue
和take()
方法存在某种锁定问题,但是对于如何进一步调试或解决该问题还没有足够的经验。
其他数据
我们注意到了一些趋势:某些线程有时占用特定的CPU使用率。例如,如果仔细观察,有时会发现一些线程的使用率分别为1.7%,1.7%,1.7%和0.7%。在另一种情况下,您可能会看到3.3%,3.3%和0.7%。在我看来,这些线程正在尝试一段特定的计算时间(?),然后放弃了,而使用率低的CPU线程实际上是在执行 tiny 工作。
我们的实例是静态的,我们为this构造函数指定了1个解码器计数(默认值为4,因为我们有4个内核-更改此值不会产生任何区别)。