首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java CPU密集型应用程序在增加no时暂停/挂起。工人们的。瓶颈在哪里?如何在Ubuntu服务器上推断/监视它?

Java CPU密集型应用程序在增加no时暂停/挂起。工人们的。瓶颈在哪里?如何在Ubuntu服务器上推断/监视它?
EN

Stack Overflow用户
提问于 2009-12-23 09:08:58
回答 3查看 846关注 0票数 0

我正在EC2服务器(c1.xlarge)上运行一个每晚使用CPU密集型的Java应用程序,该服务器有8个内核,7.5GBRAM(运行Linux / Ubuntu 9.10 (Karmic ) 64位)。

应用程序是以这样的方式设计的:构造了可变数量的工作人员(每个工作人员都在自己的线程中),并从队列中获取消息来处理它们。

吞吐量是这里关注的主要问题,性能是以处理后的消息/秒来衡量的。应用程序不受RAM限制.就我所能看到的来说,我没有去过任何地方。(虽然我不是Linux的明星。我使用dstat来检查I/O负载(相当低)和CPU等待信号(几乎不存在)。

当产生不同数量的工作人员(工作线程)时,我看到了以下情况。

  1. 工作者:吞吐量1.3消息/秒/工
  2. 工作者:~吞吐量0.8消息/秒/工
  3. 工作者:~吞吐量0.5条消息/秒/工
  4. 工作者:~吞吐量0.05条消息/秒/工

我原以为吞吐量会呈近线性增长,但事实证明并非如此。

三个问题:

  1. 是什么导致一个工人->两个工人和两个工人->三个工人的次线性表现?
  2. 当从三名工人到四名工人时,什么可能导致(几乎)完全停工?这看起来像是一种僵局--或者什么的.(这种情况是否会由于大量的上下文切换而发生?)
  3. 我将如何开始测量这些问题发生在哪里?我的开发盒有两个CPU,并且运行在windows下。我通常会附加一个GUI-分析器并检查线程问题。但这个问题只会真正表现出我的两个以上的线程。

一些更多的背景资料:

  • 使用Executors.newScheduledThreadPool生成工作人员
  • 工作线程根据消息(CPU密集型)进行计算。每个工作线程包含一个单独的persistQueue,用于卸载写入磁盘(从而利用CPU / I/O并发性)。 persistQueue =新ThreadPoolExecutor(1,1,100,TimeUnit.MILLISECONDS,新ArrayBlockingQueue(maxAsyncQueueSize),新ThreadPoolExecutor.AbortPolicy());

流程(每个工人)如下:

  1. 工作线程将消息的结果放入persistQueue中,然后继续处理下一条消息。
  2. ThreadpoolExecutor (每个工作线程有一个线程)只包含一个线程,它处理所有传入数据(在persistQueue中等待)并将其写入磁盘(伯克利数据库 + Apache 卢塞尼)。
  3. 其思想是,1和2可以在很大程度上并发运行,因为1是CPU重,2是I/O重。
  4. 有可能persistQueue变得满了。这样做是因为否则缓慢的I/O系统可能会导致队列泛滥,并导致OOM-errors (是的,这是大量的数据)。在这种情况下,workerThread暂停,直到它可以将其内容写入persistQueue。在这个设置中还没有出现完整的队列(这也是我认为应用程序绝对不受I/O限制的另一个原因)。

最后一项资料:

  • 工人与其他人有关其数据的资料是孤立的,但:
代码语言:javascript
复制
- They share some heavily used static final maps (used as caches. The maps are memory-intensive, so I can't keep them local to a worker even if I wanted to). Operations that workers perform on these caches are: iterations, lookups, contains (no writes, deletes, etc.)
- These shared maps are accessed without synchronization (no need. right?)
- Workers populate their local data by selecting data from MySQL (based on keys in the received message). So this is a potential bottleneck. However, most of the data are reads, queried tables are optimized with indexes and again not I/O-bound.
- I have to admit that I haven't done much MySQL-server optimizing yet (in terms of `config -params`), but I just don't think that is the problem.

  • 输出写入:
代码语言:javascript
复制
- Berkeley DB (using memcached(b)-client). All workers share one server.
- Lucene (using a home-grown low-level indexer). Each workers has a separate indexer.

  • 即使禁用输出写入,也会出现问题。

这是一个巨大的帖子,我意识到了,但我希望你能给我一些关于这可能是什么,或如何开始监测/推断问题所在的指点。

EN

回答 3

Stack Overflow用户

发布于 2009-12-23 09:53:09

只有侧写才有帮助。

但要检查的是:

  • 工人们从队列中得到信息。生产者队列线程保存的是哪种类型的队列?
  • 为什么要使用Executors.newScheduledThreadPool来创建员工呢?你不想让他们马上跑吗?
票数 0
EN

Stack Overflow用户

发布于 2009-12-23 10:05:44

如果我理解正确的话,多个工作人员都会从同一个队列中提取数据,进行计算,并将结果传递给他们的私人作者,例如:

代码语言:javascript
复制
              / [ worker ] - [ writer, queue ]
[ msg-queue ] - [ worker ] - [ writer, queue ]
              \ [ worker ] - [ writer, queue ]

工作人员可能会阻塞以进入msg队列,添加一个管理工作项队列的读取器可以解决此问题,如果出现此问题,如下所示:

代码语言:javascript
复制
                                   / [ worker ] - [ writer, queue ]
[ msg-queue ] - [ fetcher, queue ] - [ worker ] - [ writer, queue ]
                                   \ [ worker ] - [ writer, queue ]

我从您的描述中学到的另一件事是,计算以只读的方式使用了一组集合,因此并发性不应该是一个问题。研究使用哪种实现可能是个好主意,即使在代码中没有同步使用,默认情况下,集合类(如Vector )也会同步。

使用集合类的不可变版本将有助于确保默认情况下映射的使用是并行的。

票数 0
EN

Stack Overflow用户

发布于 2020-04-24 06:25:43

猜测您共享而不是阻塞数据结构会产生大量的内存隔离操作,破坏CPU现金。没有阻塞是不可用的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1951546

复制
相关文章

相似问题

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