【问题标题】:Java Random Slowdowns on Mac OS cont'dMac OS 上的 Java 随机减速(续)
【发布时间】:2010-12-16 20:32:54
【问题描述】:

几周前我问过这个问题,但我仍然遇到问题并且我有一些新的提示。原来的问题在这里:

Java Random Slowdowns on Mac OS

基本上,我有一个 Java 应用程序,它可以将作业拆分为独立的部分并在单独的线程中运行它们。线程没有同步或共享内存项。它们共享的唯一资源是硬盘上的数据文件,每个线程都有一个打开的文件通道。

大多数时候它运行得非常快,但偶尔它会无缘无故地运行得很慢。如果我将 CPU 分析器附加到它,那么它将再次开始快速运行。如果我拍摄 CPU 快照,它会说它大部分时间都花在“自我时间”中,该函数除了检查一些(非共享非同步)布尔值之外什么都不做。我不知道这怎么可能是准确的,因为 1,它没有任何意义,以及 2,附加分析器似乎可以将线程从它们所处的任何模式中剔除并解决问题。此外,无论它运行快还是慢,它总是完成并提供相同的输出,并且它永远不会降低总 cpu 使用率(在这种情况下约为 1500%),这意味着线程没有被阻塞。

我尝试了不同的垃圾收集器,不同的内存空间大小,将数据输出写入非 RAID 驱动器,并将所有数据输出放在线程中,将主工作线程分开。

有人知道这可能是什么问题吗?会不会是操作系统(OS X 10.6.2)?我无法在 Windows 机器上复制它,但我没有具有类似硬件配置的机器。

【问题讨论】:

  • 你能在缓慢的时间测量页面错误吗?也许是磁盘。
  • 我不认为这是分页。活动监视器显示没有页面活动,并且进程被分配了足够的内存。在这种情况下,我的机器有 32G 的内存,我分配了 16G 的最大堆大小,它最多使用大约 10G。

标签: java multithreading macos random operating-system


【解决方案1】:

回复可能有点晚了,但我可以在线程中使用 Random 观察到类似的减速,这与 java.util.Random 中使用的 volatile 变量有关 - 有关详细信息,请参阅 How can assigning a variable result in a serious performance drop while the execution order is (nearly) untouched?。如果我得到的答案是正确的(这对我来说听起来很合理),减速可能与 Random 中使用的 volatile 变量的内存地址有关(看看用户对我的“不可靠”的回答问题,这比我在这里更好地解释了这个问题)。

如果您在线程的运行方法中创建随机实例,您可以简单地尝试将它们转换为对象变量并在线程的构造函数中初始化它们:这很可能确保您的 Random 实例的 volatile 字段最终将位于 RAM 中的“不同区域”,这些区域不必在处理器内核之间同步。

【讨论】:

    【解决方案2】:

    你怎么知道它运行缓慢?当 CPU 分析器处于活动状态时,你怎么知道它运行得更快?如果您在分析器下进行整个运行,它会运行缓慢吗?如果将线程数限制为一个,它会运行缓慢吗?

    【讨论】:

    • 我有一个打印输出,偶尔会告诉我每秒处理的消息。通常它在 300,000 范围内,但是当它运行缓慢时,它是 ~15,000。当我连接 cpu 分析器时,由于分析器开销,它一直运行缓慢,但是当我断开分析器时,它开始快速运行。所以我可以通过附加和分离分析器来修复运行缓慢的过程。我从来没有能够用一个线程重现它,但它不会以任何规律发生。通常我会启动一批 100 次运行,稍后我会检查它,运行速度很慢。
    • 当它在分析器(如 netbeans 或 visualvm)中运行时,我没有复制它,因为我无法判断它是因为分析器的 b/c 运行缓慢还是由于错误。但是,当我使用 -Xprof 运行时,就会发生这种情况。
    【解决方案3】:

    其实这是一个有趣的问题,我很想知道是什么问题。

    • 首先,在您之前的问题中,您是说您在“多个”处理器之间拆分工作。它们在物理上是多重的,就像在多台机器中一样?还是多核 CPU?

    • 其次,我不确定 Snow Leopard 是否与它有关,但我们知道 SL 在多处理器机器方面引入了一些新功能。因此,新操作系统上的虚拟机可能存在一些问题。尝试使用另一个 Java 版本,我知道 SL 默认使用 Java 6。尝试使用 Java 5。

    • 第三,你有没有尝试让线程池更小一点,你说的是100个线程同时运行。例如,尝试将它们设为 20 或 40。看看有没有区别。

    • 最后,我很想看看您是如何实现多线程解决方案的。小部分代码会很好

    【讨论】:

    • 是的,它是 2 个多核 CPU,2 个具有超线程的新 Nehalem Xeons。所以我有 8 个物理核心,16 个带超线程的逻辑核心。所以我只把进程分成 15 个线程,留下一个,这样机器就可以对其他事情保持响应。我会尝试使用旧的 JDK 并告诉你。
    • 线程模型非常简单,因为问题很容易分区。我所做的只是产生 15 个完全独立的线程,没有同步或共享数据(除了一些静态常量),启动它们,然后加入它们中的每一个。
    • 让我感到疑惑的是,它怎么能跑得很慢,但仍然使用相同数量的cpu,仍然得到相同的答案。 CPU 分析结果毫无意义,就像我提到的那样,显示了在非同步方法中检查一些布尔值所花费的大量时间。
    • 在创建 15 个线程时,您实际上并没有使用 15 个内核,而是让一个空闲!它是操作系统在内核之间分配线程的责任。使用 Activity Monitor,您可以看到应用程序占用了多少线程,通常会比您自己的线程多 5-6 个。
    • 是的,还有一些,但这些线程没有做任何事情。有一些额外的错误处理线程、一些关闭钩子等,一直被阻塞。
    猜你喜欢
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 2012-03-22
    相关资源
    最近更新 更多