有没有办法告诉JVM在处理之前优化我的代码?

我有一个方法,第一次执行需要很长时间。 但经过几次调用后,时间缩短了大约30倍。 因此,为了使我的应用程序更快地响应用户交互,我使用一些关于应用程序初始化的示例数据“预热”此方法(5次)。 但这会增加应用启动时间。
我读过,JVM可以优化并编译我的java代码到本机,从而加快速度。 我想知道 – 也许有一些方法可以明确告诉JVM我希望在启动应用程序时编译这个方法?

java.lang.Compiler.compileClass

JVM在运行时进行JiT(即时)优化。 这意味着它可以分析代码的执行方式,并进行优化以提高运行时性能。 这在运行时发生。 如果您看到该方法在几次执行后变得更快,则可能是因为JiT优化(除非您的分析存在缺陷,例如,方法变得更快,因为数据变得更简单)。 如果您的分析是正确的,那么编译为native可能会对您造成伤害,因为您将不再获得运行时优化。

我们能看到这个方法吗? 您可以在不必担心JVM如何工作的情况下加快速度。 您应该准确地隔离最昂贵的操作。 您还应该validation这不是某种垃圾收集问题。 也许方法很好,但有一个GC正在咀嚼时间,当它完成时,你的方法以可接受的速度运行。

JIT优化工作得非常精确,因为它们可以优化代码实际执行的操作,而不是在不同实例中可以执行的操作。

由于输入数据不同,JITted代码甚至可能在不同的运行中不同。 甚至当环境发生变化时,它可以不止一次地重新优化。

换句话说:如果没有真正的数据,JVM将无法很好地优化代码。 (即它只能做’静态’优化)

但最后,如果你获得如此高的改进(30倍是很多!),它很可能是它的要么

  • 不是代码而是其他东西(如文件或数据库缓存)
  • 源级别的非最佳代码。 (就像一些可能会出现紧密循环的繁重计算)

编辑:

在看了你的代码之后,在Literas.prepareLiteras()一个大循环中,你不断地用不同的点调用path.contains(p)但路径相同。 SimplePath.contains()每次调用时都会创建一个边界形状,因此您最终会反复创建相同的形状。 这是应该从内循环中拉出来的一个主要例子。

我不认为JIT可以优化整个方法,但在某些极端情况下,它可能将getShape()转换为专用于单个路径的东西,并再次为下一个路径重新编译。 没有很好地利用JVM智能,嗯?

如果使用Sun JVM,则JIT编译有不同的阈值,具体取决于您使用的是客户端还是服务器JVM。 对于客户端,它是对方法的1500次调用,对于服务器,它是10000.您可以使用JVM参数-XX:CompileThreshold=100将其更改为非常低的值。

但是,如此低的门槛不会有利于您的全球业绩。 我只建议使用它,以测试热身的性能改善是否受到JIT的影响。

通过热身,我从未见过因子30的改善,这是由于JIT优化。 然而。 这总是由于一些缓存。

如果您有64位操作系统,可以尝试在64位JVM上运行它。

Oracle实现中有两个版本的JVM:客户端VM和服务器VM。 在32位Windows上,客户端VM是默认值。 在64位Windows上,服务器VM是默认设置。

客户端和服务器VM之间的区别在于它们的调整方式:服务器VM比客户端VM执行更积极的优化(并且更早地进行优化)。 服务器VM已针对长时间运行的进程优化了设置。 客户端VM具有针对桌面使用进行了优化的默认设置:它预先进行的优化较少,但启动速度更快。

我在计算密集型课程中遇到了很大的速度差异; 与32位JVM相比,这些有时在64位JVM上的运行速度是原来的两倍。

大多数情况下我都认为hvgotcodes,但问题也可能不是JVM优化,但是在最初几次运行来自磁盘的数据之后现在是在缓存中,或者前几次它仍在加载和初始化类但在那之后,他们都在记忆中。