Compilation 关于可能的java(或其他内存管理语言)优化的问题
从我所读到的内容来看,java(通常)似乎将java编译为不太优化的java字节码,而将其留给jit进行优化。这是真的吗?如果是的话,是否有任何探索(可能在替代实现中)让编译器优化代码,以减少jit的工作量(这可能吗) 此外,许多人似乎不喜欢Java(和许多其他高级内存管理语言)的本机代码生成(有时称为提前编译),原因有很多,如可移植性丧失(等等),但也有一部分原因(至少对于那些有即时编译器的语言)这种思想认为,提前编译机器代码将错过jit编译器可能完成的优化,因此从长远来看可能会更慢Compilation 关于可能的java(或其他内存管理语言)优化的问题,compilation,jit,aot,Compilation,Jit,Aot,从我所读到的内容来看,java(通常)似乎将java编译为不太优化的java字节码,而将其留给jit进行优化。这是真的吗?如果是的话,是否有任何探索(可能在替代实现中)让编译器优化代码,以减少jit的工作量(这可能吗) 此外,许多人似乎不喜欢Java(和许多其他高级内存管理语言)的本机代码生成(有时称为提前编译),原因有很多,如可移植性丧失(等等),但也有一部分原因(至少对于那些有即时编译器的语言)这种思想认为,提前编译机器代码将错过jit编译器可能完成的优化,因此从长远来看可能会更慢 这让我想
这让我想知道是否有人尝试过为java/(其他内存管理语言)实现(编译成二进制+一些额外的代码,然后运行程序并分析测试运行的运行时信息,以生成一个更优化的二进制代码,以供实际使用),以及这与jit代码相比会如何?有人知道吗?就我个人而言,我认为最大的区别不是JIT编译和AOT编译之间的区别,而是类编译和整个程序优化之间的区别 运行javac时,它只查看单个.java文件,并将其编译成单个.class文件。所有的接口实现、虚拟方法和重写都经过了有效性检查,但没有得到解决(因为不分析整个程序就不可能知道真正的方法调用目标) JVM使用“运行时加载和链接”将所有类组装成一个连贯的程序(程序中的任何类都可以调用专门的行为来更改默认的加载/链接行为) 但是,在运行时,JVM可以删除绝大多数虚拟方法。它可以内联所有getter和setter,将它们转换为原始字段。当这些原始字段内联时,它可以执行常量传播以进一步优化代码。(在运行时,没有私有字段)并且如果只有一个线程在运行,JVM可以消除所有同步原语
长话短说,如果不分析整个程序,有很多优化是不可能的,而进行整个程序分析的最佳时间是在运行时 官方Java热点编译器在运行时进行“自适应优化”,这与您提到的概要文件引导优化基本相同。这至少是这个特定Java实现的一个特性已经有很长时间了 在编译时执行更多的静态分析或优化过程的代价本质上是您从这一额外工作中获得的(不断减少的)回报与编译器运行所需的时间。像MLton(标准ML)这样的编译器是一个使用大量静态检查的全程序优化编译器。它产生非常好的代码,但在中大型程序上,甚至在快速系统上,速度变得非常非常慢
因此,Java方法似乎尽可能多地使用JIT和自适应优化,初始编译过程只是生成一个可接受的有效二进制文件。绝对相反的目的是使用类似MLKit的方法,它对区域和内存行为进行大量静态推断。配置文件引导优化有一些注意事项,甚至在您链接的Wiki文章中也提到了其中之一。它的结果是有效的
- 对于给定的示例,表示用户或其他代码实际使用代码的方式
- 对于给定的平台(CPU、内存+其他硬件、操作系统等)。
从性能的角度来看,即使在通常被认为(或多或少)相同的平台之间,也存在着很大的差异(例如,将单核、512M的旧Athlon与在Linux上运行但内核版本非常不同的6核、8G的Intel进行比较) - 对于给定的JVM及其配置李>
使用真实数据(使用统计+平台+配置)可以避免前面提到的警告 它的代价是它需要花费一些额外的时间来“分析”+JIT。大部分时间都过得很好 我猜概要文件引导的优化器仍然可以与之竞争(甚至击败它),但只有在某些特殊情况下,如果您能够避免这些警告:
- 您非常确信您的示例很好地代表了现实生活中的场景,并且在执行过程中不会有太多的变化
- 您非常准确地了解您的目标平台,并且可以在其上进行评测
- 当然,您知道/控制JVM及其配置