4

这些事情显然需要仔细检查和代码可用性来彻底分析并给出好的建议。然而,这并不总是可行的,我希望可以根据我在下面提供的信息为我提供好的提示。

我有一个使用侦听器线程来侦听传入数据的服务器应用程序。传入的数据被解释为特定于应用程序的消息,然后这些消息会引发事件。

到目前为止,我对事情的完成方式并没有任何控制权。

因为这是一个遗留应用程序,所以这些事件以前由同一个侦听器线程(主要是单线程应用程序)处理。这些事件被发送到一个黑盒,并产生一个应该写入磁盘的结果。

为了提高吞吐量,我想使用一个线程池来处理这些事件。这个想法是侦听器线程可以在每次创建事件时生成新任务,并且线程将负责黑盒调用。最后,我有一个后台线程执行写入磁盘。

仅使用以前的设置和后台编写器,一切正常,吞吐量是以前的约 1.6 倍。

当我添加线程池时,性能会下降。一开始,一切似乎都运行顺利,但过了一会儿,一切都变得非常缓慢,最后我得到了 OutOfMemoryExceptions。奇怪的是,当我每次将任务添加到池中时打印活动线程的数量(以及有关排队的任务数量等信息)时,看起来线程池跟上没有问题生产者(监听线程)。

使用 top -H 检查 CPU 使用情况,一开始它分布得很均匀,但最后工作线程几乎没有活动,只有侦听器线程处于活动状态。然而它似乎并没有提交更多的任务......

任何人都可以假设这些症状的原因吗?您是否认为遗留代码中的某些内容(我无法控制)更有可能在添加多个线程时变坏?内存不足的问题应该是因为某处的某些队列变得太大,但是由于线程池几乎从不包含排队的任务,所以不可能是这样。

欢迎任何想法。特别是关于如何更有效地诊断这种情况的想法。我怎样才能更好地了解我的线程正在做什么等。

谢谢。

4

4 回答 4

5

减慢然后内存不足意味着内存泄漏。

因此,我将首先使用一些 Java 内存分析器工具来识别是否存在泄漏以及正在泄漏的内容。有时你很幸运,泄漏的对象是众所周知的,很清楚谁在坚持他们不应该做的事情。

于 2011-07-26T15:22:04.917 回答
4

谢谢你的回答。我阅读了 Java VisualVM 并将其用作工具。结果和结论详述如下。希望这些图片能工作足够长的时间。

我首先运行程序并创建了一些堆转储,认为我可以分析转储并查看占用所有内存的内容。这可能会起作用,除非转储文件变得如此之大并且我的工作站在尝试访问它时使用有限。一个手术等了两个小时后,我意识到我做不到。

所以我的下一个选择是我愚蠢的,没有想过的事情。我可以减少发送到应用程序的消息数量,并且内存使用量增加的趋势应该仍然存在。此外,转储文件将更小,分析速度更快。

事实证明,当以较慢的速度发送消息时,没有出现内存不足的问题!下面可以看到内存使用情况的图表。

慢发送

峰值是累积内存分配的结果,随后的低谷是在垃圾收集器运行之后。尽管内存使用量肯定是相当惊人的,并且可能存在问题,但无法观察到内存泄漏的长期趋势。

我开始逐步提高每秒发送消息的速率,以查看应用程序在哪里碰壁。下图显示了与上一个非常不同的场景......

快速发送

因为当发送消息的速率增加时会发生这种情况,我的猜测是我释放侦听器线程会导致它能够非常快速地接受大量消息,这会导致越来越多的分配。垃圾收集器不运行,内存使用量碰壁。

这个问题当然还有更多,但鉴于我今天发现的情况,我对从这里去哪里有一个相当好的想法。当然,欢迎任何其他建议/意见。

这个问题可能应该重新归类为处理内存使用而不是线程池......线程池根本不是问题。

于 2011-07-27T12:16:58.907 回答
2

我同意@djna。java并发包的线程池工作。如果不需要线程,它不会创建线程。您会看到线程数符合预期。这意味着您的遗留代码中的某些内容可能还没有为多线程做好准备。例如,某些代码片段不同步。因此,某些元素不会从集合中删除。或者一些额外的元素存储在集合中。因此,内存使用量正在增长。

顺便说一句,我现在不完全了解应用程序的哪一部分使用线程池。您是否有一个线程来处理事件,而现在您有多个线程来执行此操作?您是否可能更改了线程间通信机制?增加了队列?这可能是您调查的另一个方向。

祝你好运!

于 2011-07-26T15:32:42.233 回答
1

正如 djna 所提到的,这可能是某种类型的内存泄漏。我的猜测是您在某处保留对请求的引用:

  • 在排队请求的调度程序线程中
  • 在处理请求的线程中
  • 在处理请求的黑匣子中
  • 在写入磁盘的写入器线程中。

由于您说在将线程池添加到混合中之前一切正常,我的猜测是池中的线程在某处保留对请求的引用。想法是,如果没有线程池,您就不会重用线程,因此信息会消失。

根据 djna 的建议,您可以使用 Java 内存分析器来帮助确定数据堆积在哪里。

于 2011-07-26T15:30:38.210 回答