我有一个从C移植到Java的程序。两个应用程序都使用快速排序来订购一些分区数据(基因组坐标)。
Java版本运行速度很快,但我想让它更接近C版本。我正在使用Sun JDK v6u14。
显然我无法与C应用程序保持一致,但我想了解我可以做些什么来尽可能地提高性能(在环境范围内)。
我可以做些什么来测试应用程序的不同部分,内存使用情况等的性能?具体来说,我该怎么做?
此外,我可以实现哪些技巧(通常)来更改类和变量的属性和组织,减少内存使用并提高速度?
编辑:我使用Eclipse,显然更喜欢任何第三方工具的免费选项。谢谢!
答案 0 :(得分:32)
不要试图超越jvm。
特别是:
不要试图避免创建对象 为了表现
使用不可变对象 适用。
使用对象的范围 正确的,这样GC就可以做到 工作
在你指的地方使用原语 原语(例如,非可空的int 与可空的整数相比)
使用内置算法和数据结构
处理并发时使用java.util.concurrent包。
对性能的正确性。首先做好,然后测量,然后用剖析器进行测量,然后进行优化。
答案 1 :(得分:11)
显然,个人资料资料个人资料。对于Eclipse,有TPTP。这是关于TPTP plugin for Eclipse的文章。 Netbeans有自己的profiler。 jvisualvm作为独立工具很不错。 (整个dev.java.net服务器目前似乎已经停止,但它非常活跃。)
首先要做的是使用库排序例程Collections.sort;这将要求您的数据对象为Comparable。这可能足够快,肯定会提供良好的基线。
一般提示:
StringBuilder
(不是StringBuffer
,因为我刚才提到的那个锁定事物)而不是连接String
个对象final
;如果可能的话,让你的课程完全不可改变ArrayList
(甚至是数组),因此您访问的内存是连续的,而不是像LinkedList
答案 2 :(得分:5)
使用分析器:
使用提供商提供的最新版本的JVM。顺便提一下,Sun的Java 6更新14确实带来了performance improvements。
答案 3 :(得分:4)
不要过早优化。
衡量绩效,然后进行优化。
尽可能使用最终变量。它不仅允许JVM 优化更多,也让你的 代码更易于阅读和维护。
如果使对象不可变,则不必克隆它们。
首先通过更改算法进行优化,然后通过更改实现进行优化。
有时您需要采用旧式技术,例如循环展开或缓存预先计算的值。记住它们,即使它们看起来不好看,它们也很有用。
答案 4 :(得分:3)
另外尝试调整VM的运行时参数 - 例如,VM的最新版本包含以下标志,可以在某些情况下提高性能。
-XX:+DoEscapeAnalysis
答案 5 :(得分:2)
jvisualvm现在附带JDK 6 - 这就是上面引用的链接不起作用的原因。只需输入“jvisualvm< pid>”,其中< pid>是您要跟踪的进程的ID。你将会看到如何使用堆,但你不会看到填充它的是什么。
如果这是一个长时间运行的过程,您可以在运行时打开-server选项。您可以使用许多调整选项;那只是一个。
答案 6 :(得分:2)
首先需要注意的是 - 在开始任何优化工作之前,请确保已完成适当的分析或基准测试。结果通常可以启发你,并且几乎总能为你节省大量精力来优化无关紧要的事情。
假设您确实需要它,那么您可以在Java中获得与C相当的性能,但需要花费一些精力。您需要知道JVM在哪里做“额外工作”并避免这些。
特别是:
double
而不是Double
。答案 7 :(得分:1)
如果您的算法占用大量CPU,您可能需要考虑利用并行化。您可以在多个线程中进行排序,并在以后合并结果。
然而,这并不是一个轻率的决定,因为编写并发代码很难。
答案 8 :(得分:1)
您不能使用Java库中包含的排序函数吗?
您至少可以查看两个排序函数之间的速度差异。
答案 9 :(得分:0)
方法论上,您必须对应用程序进行概要分析,然后了解程序的哪些组件是时间和内存密集型的:然后仔细查看这些组件,以提高其性能(请参阅{{3} })。
从纯粹的技术POV,你可以使用一些java-to-nativecode编译器,比如Excelsior的jet,但我要注意最近的JVM非常快,所以VM不应该以有意义的方式影响。
答案 10 :(得分:0)
您的排序代码只执行一次,例如在命令行实用程序中,只需对其进行排序或多次,例如一个响应某些用户输入而进行排序的webapp?
有可能在代码执行几次后性能会显着提高,因为如果HotSpot VM决定您的代码是热点,它可能会积极优化。
与C / C ++相比,这是一个很大的优势。
VM在运行时优化了经常使用的代码,并且它做得非常好。因此,性能实际上可以超过C / C ++。真。 ;)
但是,您的自定义比较器可能是一个优化的地方。
尝试在更昂贵的东西(例如字符串比较)之前首先检查廉价的东西(例如int比较)。我不确定这些提示是否适用,因为我不知道你的比较器。
使用Collections.sort(列表,比较器)或Arrays.sort(数组,比较器)。数组变体会更快一些,请参阅相应的文档。
正如安德烈亚斯之前所说:不要试图超越虚拟机。
答案 11 :(得分:0)
除了代码的微优化之外,可能还存在其他性能增强路径。如何使用不同的算法来实现您希望程序执行的操作?可能是一个不同的数据结构?
或者交换一些磁盘/ ram空间以提高速度,或者如果你可以在加载程序期间预先放弃一些时间,你可以预先计算查找表而不是进行计算 - 这样,处理速度很快。即,可以对其他资源进行一些权衡。
答案 12 :(得分:0)
Here's what I would do, in any language.如果样本显示您的排序比较例程在很长一段时间内处于活动状态,您可能会找到一种简化它的方法。但也许时间在其他地方。在修复任何事情之前先诊断,看看有什么坏了。如果你解决了最重要的事情,那么很有可能,那么其他事情将是最重要的事情,等等,直到你真正获得了相当不错的加速。
答案 13 :(得分:0)
配置并调整您的java程序和主机。大多数代码遵循80/20规则。这是20%的代码80%的时间,所以找到20%并尽可能快地完成。例如,文章Tuning Java Servers(http://www.infoq.com/articles/Tuning-Java-Servers)提供了从命令行向下钻取的描述,然后使用Java Flight recorder,Eclipse Memory Analyzer和JProfiler等工具隔离问题。