与命令行相比,为什么我的应用程序在IntelliJ中运行得更快?

时间:2011-08-18 16:52:45

标签: java performance ide

我们有一个应用程序通过拆分数据并对其进行排序来导入大量文件。运行JUnit测试用例时,整个过程大约需要 16分钟

同样的测试,mvn clean test -Dtest=MyTest 34分钟中完成。

我们正在呼叫/bin/sort对文件进行排序。这种情况似乎需要更长的时间。我不明白有什么不同。

查看IntelliJ,它与

一起运行
/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Home/bin/java -Didea.launcher.port=7532 -Didea.launcher.bin.path=/Applications/IntelliJ IDEA 10.app/bin -Dfile.encoding=UTF-8 -classpath %classhpath% com.intellij.rt.execution.application.AppMain com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 xxx.IntTestImportProcess,testImportProcess

我在OS X上。所有类都是使用Spring注入的。有哪些可能的建议是关于IntelliJ中这种性能提升背后的理论?测试是相同的。我无法分享所有代码,因为有这么多。但是我可以根据要求添加任何细节。

这是我的主要课程,以及我如何运行这两个课程。

public static void main(String... args) throws IOException {
        if(args.length != 2) {
            System.out.println("Usage: \n  java -jar client.jar spring.xml data_file");
            System.exit(1);
        }
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext(args[0]);
        PeriodFormatter formatter = new PeriodFormatterBuilder()
                .appendMinutes()
                .appendSuffix("minute", "minutes")
                .appendSeparator(" and ")
                .appendSeconds()
                .appendSuffix("second", "seconds")
                .toFormatter();
        URI output = (URI) applicationContext.getBean("workingDirectory");
        File dir = new File(output);
        if(dir.exists()) {
            Files.deleteDirectoryContents(dir.getCanonicalFile());
        }
        else {
            dir.mkdirs();
        }
        ImportProcess importProcess = applicationContext.getBean(ImportProcess.class);
        long start = System.currentTimeMillis();
        File file = new File(args[1]);
        importProcess.beginImport(file);
        Period period = new Period(System.currentTimeMillis() - start); // in milliseconds
        System.out.println(formatter.print(period.toPeriod()));
    }

我决定删除JUnit并使用main()方法。结果完全一样。 IntelliJ又来了。这是疯狂的日志。

使用IntelliJ

DEBUG [ main] 2011-08-18 13:05:16,259 [er.DelimitedTextUnixDataSorter] Sorting file [/Users/amirraminfar/Desktop/import-process/usage]
DEBUG [ main] 2011-08-18 13:06:09,546 [er.DelimitedTextUnixDataSorter] Sorting file [/Users/amirraminfar/Desktop/import-process/customer]

使用java -jar

DEBUG [ main] 2011-08-18 12:10:16,726 [er.DelimitedTextUnixDataSorter] Sorting file [/Users/amirraminfar/Desktop/import-process/usage]
DEBUG [ main] 2011-08-18 12:15:55,893 [er.DelimitedTextUnixDataSorter] Sorting file [/Users/amirraminfar/Desktop/import-process/customer]

sort命令是

sort -t'    ' -f -k32,32f -k18,18f -k1,1n

如上所示,在Intellij中排序需要 1分钟,但在java -jar需要 5分钟

更新

我使用/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Home/bin/java运行了一切,排序仍然需要超过5分钟。

6 个答案:

答案 0 :(得分:9)

谢谢大家的帮助。事实证明IntelliJ开始与LANG=C排序。 Mac OS X终端默认在UTF8中排序,这解释了性能损失。希望这个答案会对某人有所帮助。

答案 1 :(得分:1)

mvn clean正在重建项目吗?在IDEA下运行不是这样吗?使用Maven构建项目需要18分钟(如果确实如此,我会不会感到惊讶,因为Maven是绝对的坑)?

如果所有这些问题的答案都是'是',那么我认为你得出结论。

解决方案是将Maven带到树林里,拍摄它,然后把它埋在一个没有标记的坟墓里。

答案 2 :(得分:1)

猜测不仅仅是证实的答案:

很多可能依赖于I / O缓冲。排序超过500K的记录将输出大量数据,因此正确的缓冲区大小可能会很重要。我认为tty通常是行缓冲的,所以它将做500K读取&写操作,IDE可能只是读取更大的缓冲区。

此外,OSX可能具有过程或I / O调度,这些调度非常有利于GUI应用程序而不是控制台应用程序(可以通过绑定到tty来检测),因此可能需要等待&从控制台闲置的时间远远多于IDE中的空闲时间。

答案 3 :(得分:0)

这个问题没有完全正确定义,而且远非明确。 您是说您使用Java IO读出文件夹中的文件列表,然后将其传递给外部进程进行排序? 对我来说听起来有点奇怪的解决方案,但无论如何,这必须与内存有关。使用JConsole连接到这两个应用程序,并在图表中查找线索。

答案 4 :(得分:0)

mvn可能正在启动一个具有与IDE不同的选项的JVM。

Real differences between "java -server" and "java -client"?可能会导致长时间运行的应用程序性能出现重大差异,但有时候gc标记的差异会导致应用程序以不同方式使用内存时出现性能差异。

如果您的进程受内存限制,因此在某些内存级别发生崩溃,那么-Xmx等堆标志也会对性能产生巨大影响。内存分析可以轻松地对此进行排除。

要诊断这些差异,请查看您的mvn配置文件以了解它是如何启动JVM的,并查看您的IDE Java应用程序启动器配置。

答案 5 :(得分:0)

您是否尝试使用VisualVM等分析器来查看瓶颈是什么?还要比较计算机的CPU使用率图表(Mac应该有一些系统监视器)。也许这个过程在某些时候是阻塞而不能有效地工作,这可以看作是不同形状的CPU使用率图。