【问题标题】:JVM running on IDE takes more processing power than running on command line在 IDE 上运行的 JVM 比在命令行上运行需要更多的处理能力
【发布时间】:2013-09-23 06:12:19
【问题描述】:

我遇到了一个非常令人沮丧的问题。我使用 IDE 来开发我的应用程序。我通过 IDE 中的执行时间监控性能,但不幸的是,当我将类导出到 Jar 文件时,它在命令行上的运行速度慢了 7 倍。我检查了我的 JVM 并确保相同的 JVM 链接到两个执行。为命令行分配了更多堆内存。

后来,我使用了一个进程性能监控工具,同时运行了两个应用程序(在 CMD 和 IDE 上)。我注意到除了 CPU 能力之外,这两个进程在所有方面都是相同的。在 IDE 上运行的进程占用了大约 19%-23% 的 CPU 使用率,而在 CMD 上运行的进程占用了大约 6%-11% 的 CPU 使用率。这或许可以解释为什么在 IDE 上运行所需的时间更少。

为了让应用更清晰,下面是花费最多的一段代码

                         for (Call call: calls {

                            CallXCD callXCD = call.getCallXCD();    
                            if(callXCD.isOnNet()){
                                System.out.println("OnNet");
                            }
                            else if (callXCD.isXNet()){
                                System.out.println("XNet");

                            }
                            else if (callXCD.isOthers()){
                                System.out.println("Others");

                            }
                            else if (callXCD.isIntra()){
                                System.out.println("Intra");
                            }
                            else {
                                System.out.println("Not Known");
                            }
                         }

CallXCD 是一个包含多个字符串变量和几个方法(如 isOnNet 和 isXNet)的对象。这些方法对对象的字符串应用 compareTo() 方法,并根据此比较返回 true 或 false。

我通过打印每次迭代花费的时间来分析这段代码。在 IDE 中,每次迭代大约需要 0.007 毫秒,而在命令行中运行 jar 文件大约需要 0.2 毫秒。因为我的代码对此进行了大约 400 万次迭代,所以对性能的负面影响非常显着

为什么会这样?有没有办法像内存参数一样为 JVM 分配更多的处理能力。

【问题讨论】:

  • 在IDE中,你在调试吗?您的应用程序做什么?请注意,两者之间的 IO 跟踪根本不同,所以我不确定你从哪里得到这样的想法,即进程“除了 CPU 能力之外的一切都相同”。
  • 您好 Jon,即使我删除了所有 System.out.print,也会发生同样的行为。为了更清楚地了解性能。我分析了某些循环了 400 万次的方法。该方法在 IDE 上执行平均需要 0.007 毫秒,而在命令行上执行平均需要 0.2 毫秒
  • 那么有任何输出吗?对于您的代码在做什么,我们真的是在盲目地操作。一个简短但完整的程序来演示这个问题真的很有帮助。
  • @Jon,我编辑了我的帖子以包含导致问题的部分。目前我不做任何输出,但需要打印时间。即使我删除了打印时间,我的秒表也没有任何变化。我不认为这是印刷的事情。您认为快照的处理能力差异背后有原因吗??
  • 您不会认为是打印 - 但鉴于命令行上的输出与 IDE 中的输出非常不同,您应该对其进行验证。一般来说,在基准测试时包含不必要的 IO 是一个非常糟糕的主意。我建议你去掉 System.out 调用,除了最上面的结果(即在你完成计时后只写一次整体结果)。

标签: java eclipse jar jvm executable-jar


【解决方案1】:

(在 cmets 对话后。)

这似乎是由于在命令行和 IDE 中处理控制台输出的方式不同。这些在自动滚动、缓冲区大小等方面的行为可能会有很大不同。

通常,在对代码进行基准测试时,最好将您真正感兴趣的代码与任何可能干扰结果的诊断输出隔离开来。如果您绝对必须包含诊断输出,则将其写入文件(可能在 ram 磁盘上)有助于减少控制台实现之间的差异。

【讨论】:

    【解决方案2】:

    也许您的 IDE 有不同的 JVM 选项来运行您的进程?较大的堆大小 (-Xmx) 可以降低垃圾收集成本。如果您的应用程序是内存密集型且因堆大小不足而阻塞,这很容易成为问题。

    IDE 通常还会通过管道传输进程的标准输入/输出。我不知道这是否会比标准输出到控制台更有效,但如果您要打印/记录很多,这可能是一个需要考虑的因素。

    正如 Jon Skeet 所说,左右 I/O 走线明显不同。

    IDE 在调试模式下所做的第三件主要事情是作为调试器附加到您的进程。但这通常会使过程变慢,而不是更快。

    总结:最好检查一下 IDE 的 JVM 选项和启动配置。可能是使用不同的参数、在不同的工作目录中运行,或者堆大小太小。

    【讨论】:

      【解决方案3】:

      当 IDE (eclipse) 使用比从命令行启动时使用的更新的 Java 版本时,我已经看到了这种效果。此外,从 Eclipse 中运行时,您可能使用的是服务器 VM,而在命令行上使用的是客户端 JVM。这可以在运行配置或 wirkspace JVM 设置中设置(当您在“已安装的 JRE”首选项页面中单击“编辑 JRE”时为“默认 VM 参数”)。

      所以,首先确保使用相同的参数。将在 eclipse 中启动时使用的参数添加到命令行。

      【讨论】:

      • 请您帮助我如何从 Eclipse 中提取确切的参数。我导航到 Run>Run Configurations> arguments 并没有发现任何参数
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-25
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      • 2019-06-29
      • 1970-01-01
      相关资源
      最近更新 更多