Java是否保存其运行时优化?

时间:2020-03-05 18:54:49  来源:igfitidea点击:

我的教授在一个小程序上做了一个非正式的基准测试,Java时间是:第一次运行为1.7秒,之后运行为0.8秒。

  • 这是否完全是由于将运行时环境加载到了操作环境中?或者
  • 它是否受Java优化代码并存储这些优化结果的影响(对不起,我不知道其技术术语)?

解决方案

回答

我不知道任何广泛使用的虚拟机可以保存程序调用之间的统计使用情况数据,但是对于将来的研究来说,这无疑是一个有趣的可能性。

我们所看到的几乎可以肯定是由于磁盘缓存。

回答

Java JVM(实际上可能会因JVM的不同实现而有所不同)在首次启动时将解释字节码。一旦它检测到代码将运行足够多次,以JIT将其运行为本机语言,则运行速度将更快。

回答

好吧,我找到了我读过的地方。全部来自" Learning Java"(O'Reilly 2005):

The problem with a traditional JIT compilation is that optimizing code takes time. So a JIT compiler can produce decent results but may suffer a significant latency when the application starts up. This is generally not a problem for long-running server-side applications but is a serious problem for client-side software and applications run on smaller devices with limited capabilities. To address this, Sun's compiler technology, called HotSpot, uses a trick called adaptive compilation. If you look at what programs actually spend their time doing, it turns out that they spend almost all their time executing a relatively small part of the code again and again. The chunk of code that is executed repeatedly may be only a small fraction of the total program, but its behavior determines the program's overall performance. Adaptive compilation also allows the Java runtime to take advantage of new kinds of optimizations that simply can't be done in a statically compiled language, hence the claim that Java code can run faster than C/C++ in some cases.
  
  To take advantage of this fact, HotSpot starts out as a normal Java bytecode interpreter, but with a difference: it measures (profiles) the code as it is executing to see what parts are being executed repeatedly. Once it knows which parts of the code are crucial to performance, HotSpot compiles those sections into optimal native machine code. Since it compiles only a small portion of the program into machine code, it can afford to take the time necessary to optimize those portions. The rest of the program may not need to be compiled at all—just interpreted—saving memory and time. In fact, Sun's default Java VM can run in one of two modes: client and server, which tell it whether to emphasize quick startup time and memory conservation or flat out performance.
  
  A natural question to ask at this point is, Why throw away all this good profiling information each time an application shuts down? Well, Sun has partially broached this topic with the release of Java 5.0 through the use of shared, read-only classes that are stored persistently in an optimized form. This significantly reduces both the startup time and overhead of running many Java applications on a given machine. The technology for doing this is complex, but the idea is simple: optimize the parts of the program that need to go fast, and don't worry about the rest.

我有点想知道自Java 5.0以来Sun已经走了多远。

回答

我同意这可能是磁盘缓存的结果。

仅供参考,IBM Java 6 VM确实包含一个提前编译器(AOT)。该代码的优化程度不如JIT产生的代码那样好,但是它存储在多个VM中,我相信这种持久性共享内存是可以实现的。它的主要好处是可以提高启动性能。在被调用1000次之后,IBM VM默认情况下会JITs一个方法。如果知道在VM启动期间某个方法将被调用1000次(请考虑使用诸如java.lang.String.equals(...)之类的常用方法),则将其存储在AOT缓存,因此它永远不必浪费时间在运行时进行编译。

回答

我同意,发布者看到的性能差异很可能是由于磁盘延迟将JRE带入内存引起的。即时编译器(JIT)不会对小应用程序的性能产生影响。

Java 1.6u10(http://download.java.net/jdk6/)在后台进程(即使Java没有运行)中接触运行时JAR,以将数据保留在磁盘缓存中。这显着减少了启动时间(这对于桌面应用程序而言是一个巨大的好处,但对服务器端应用程序而言可能只是微不足道的价值)。

在大型,长期运行的应用程序上,JIT随时间变化很大,但是JIT积累足够的统计数据以进行启动和优化所需的时间(5-10秒)相比于JIT的总寿命非常短。应用程序(最长时间运行数月)。虽然存储和恢复JIT结果是一项有趣的学术活动,但实际的改进并不是很大(这就是为什么JIT团队将更多的精力放在诸如GC策略上,以最大限度地减少内存缓存未命中之类的原因)。

运行时类的预编译确实对桌面应用程序有很大帮助(就像前面提到的6u10磁盘高速缓存预加载一样)。

回答

我们应该描述基准测试的完成方式。尤其是在这一点上,我们开始测量时间。

如果我们包括JVM启动时间(这对于基准化用户体验很有用,但对于优化Java代码却没有太大用处),那么它可能是文件系统的缓存效果,也可能是由" Java类数据共享"功能引起的:

对于Sun:

http://java.sun.com/j2se/1.5.0/docs/guide/vm/class-data-sharing.html

这是JVM将运行时类的准备好的映像保存到文件中的一个选项,以便在下次启动时可以更快地加载(和共享)它们。我们可以使用Sun JVM的-Xshare:on或者-Xshare:off来控制它。缺省值为-Xshare:auto,如果存在共享目录映像,它将加载共享类映像;如果不存在,它将在首次启动时将其写入(如果该目录具有写权限)。

使用IBM Java 5,它的功能更加强大:

http://www.ibm.com/developerworks/java/library/j-ibmjava4/

我不知道有任何主流的JVM保存JIT统计信息。