我的教授在一个小程序上做了一个非正式的基准测试,Java时间为:第一次运行1.7秒,之后运行0.8秒。
这是否完全归因于将运行时环境加载到操作环境中?
OR
是否受到Java优化代码和存储优化结果的影响(对不起,我不知道技术术语)?
答案 0 :(得分:5)
好的,我找到了我读到的地方。这完全来自“学习Java”(O'Reilly 2005):
传统JIT编译的问题在于优化代码需要时间。因此,JIT编译器可以产生不错的结果,但在应用程序启动时可能会遇到严重的延迟。对于长时间运行的服务器端应用程序而言,这通常不是问题,但对于在功能有限的较小设备上运行的客户端软件和应用程序来说,这是一个严重的问题。为了解决这个问题,Sun的编译器技术HotSpot使用了一种称为自适应编译的技巧。如果你看看实际花费时间做什么程序,事实证明他们几乎所有的时间花在一次又一次地执行相对较小的代码部分。重复执行的代码块可能只占整个程序的一小部分,但其行为决定了程序的整体性能。自适应编译还允许Java运行时利用无法在静态编译语言中完成的新类型优化,因此声称Java代码在某些情况下可以比C / C ++运行得更快。
为了利用这一事实,HotSpot最初只是一个普通的Java字节码解释器,但有一点不同:它在执行时测量(配置)代码以查看重复执行的部分。一旦知道代码的哪些部分对性能至关重要,HotSpot就会将这些部分编译成最佳的本机代码。由于它只将程序的一小部分编译成机器代码,因此可以花费时间来优化这些部分。程序的其余部分可能根本不需要编译 - 只是解释 - 节省内存和时间。事实上,Sun的默认Java VM可以运行两种模式之一:客户端和服务器,它告诉它是否要强调快速启动时间和内存保护或平稳性能。
此时要提出的一个自然问题是,为什么每次应用程序关闭时都会抛弃所有这些良好的分析信息?好吧,Sun通过使用以优化形式持久存储的共享只读类,通过Java 5.0的发布部分地讨论了这一主题。这显着减少了在给定计算机上运行许多Java应用程序的启动时间和开销。这样做的技术很复杂,但想法很简单:优化程序中需要快速完成的部分,而不用担心其余部分。
我有点想知道自Java 5.0以来Sun已经走了多远。
答案 1 :(得分:4)
我不知道任何广泛使用的虚拟机可以在程序调用之间保存统计使用数据 - 但它确实是未来研究的一个有趣的可能性。
您所看到的几乎可以肯定是由于磁盘缓存。
答案 2 :(得分:2)
我同意这可能是磁盘缓存的结果。
仅供参考,IBM Java 6 VM确实包含一个提前编译器(AOT)。代码不像JIT生成的那样优化,但它存储在VM中,我相信某种持久的共享内存。它的主要好处是提高启动性能。默认情况下,IBM VM在调用1000次后对其进行JIT。如果它知道一个方法将在VM启动期间被调用1000次(想想一个常用的方法,如java.lang.String.equals(...)
),那么将它存储在AOT缓存中是有益的,这样它就永远不会浪费时间在运行时编译。
答案 3 :(得分:1)
我同意海报看到的性能差异很可能是由于磁盘延迟将JRE带入内存引起的。 Just In Time编译器(JIT)不会对一个小应用程序的性能产生影响。
Java 1.6u10(http://download.java.net/jdk6/)在后台进程中触及运行时JAR(即使Java未运行),以将数据保存在磁盘缓存中。这大大减少了启动时间(这对桌面应用程序来说是一个巨大的好处,但对服务器端应用程序来说可能是微不足道的。)
在大型,长期运行的应用程序中,JIT随着时间的推移会产生很大的不同 - 但JIT积累足够的统计数据以启动和优化(5-10秒)所需的时间非常非常短应用程序的整体寿命(大多数运行数月和数月)。虽然存储和恢复JIT结果是一项有趣的学术练习,但实际改进并不是很大(这就是为什么JIT团队更专注于GC策略以减少内存缓存未命中等等)。
运行时类的预编译确实对桌面应用程序有很大帮助(就像前面提到的6u10磁盘缓存预加载一样)。
答案 4 :(得分:1)
您应该描述您的基准测试是如何完成的。特别是在那时你开始测量时间。
如果包含JVM启动时间(这对于标记用户体验非常有用,但对优化Java代码没那么有用)那么它可能是文件系统缓存效果,也可能是由称为“Java类数据共享”的功能引起的“:
对于Sun:
http://java.sun.com/j2se/1.5.0/docs/guide/vm/class-data-sharing.html
这是一个选项,JVM将运行时类的准备好的映像保存到文件中,以便在下次启动时更快地加载(和共享)那些。您可以使用-Xshare:on或-Xshare:off使用Sun JVM来控制此操作。默认值为-Xshare:auto,它将加载共享类图像(如果存在),如果不存在,它将在首次启动时写入,如果该目录是可写的。
使用IBM Java 5,这是BTW更强大的功能:
http://www.ibm.com/developerworks/java/library/j-ibmjava4/
我不知道任何主流JVM正在保存JIT统计信息。
答案 5 :(得分:0)