GameServer高CPU调试-罪魁祸首:多线程WebSocketServer?

时间:2018-09-13 19:05:08

标签: java multithreading websocket garbage-collection profiling

背景

我们有一个在网络浏览器中播放的快节奏多人在线游戏。通过安全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的主版本,但是由于添加了一些调试语句,因此某些代码行可能会略有偏离)。我们怀疑LinkedBlockingQueuetake()方法存在某种锁定问题,但是对于如何进一步调试或解决该问题还没有足够的经验。

其他数据

  • 我们注意到了一些趋势:某些线程有时占用特定的CPU使用率。例如,如果仔细观察,有时会发现一些线程的使用率分别为1.7%,1.7%,1.7%和0.7%。在另一种情况下,您可能会看到3.3%,3.3%和0.7%。在我看来,这些线程正在尝试一段特定的计算时间(?),然后放弃了,而使用率低的CPU线程实际上是在执行 tiny 工作。

  • 我们的实例是静态的,我们为this构造函数指定了1个解码器计数(默认值为4,因为我们有4个内核-更改此值不会产生任何区别)。

  • 更多演示(firstsecondthirdfourth
  • 服务器正在运行Ubuntu 17.10,我们已经尝试了java-8-openjdk-amd-64和java-10-oracle,没什么区别。
  • 我们几乎可以直接使用库,而无需更改设置。我们确实禁用了nagle的算法(link)。
  • 我们尝试使用-Xmx3g和-Xms3g以及其他一些选项为jar提供额外的内存,似乎没有任何帮助。
  • jstack所示,我们还在私有后端中使用Kryonet,以使其他服务器相互通信。

0 个答案:

没有答案