.net 为什么不到处使用JIT(即时)编译器呢?

.net 为什么不到处使用JIT(即时)编译器呢?,.net,jvm,jit,.net,Jvm,Jit,我最近了解到,JIT编译器用于将与平台无关的代码编译为本机代码。JVM和.net运行时环境使用它,以获得更好的性能和显著减少编译时间。我的问题是,为什么直接编译成本机代码的普通编译器(如c编译器)也不能作为JIT?JIT编译器的使用是否有限制或规范?像大多数C编译器(如GCC)一样,提前优化编译器可能会产生比JIT编译器更好的机器代码。但是提前编译器通常需要更多的时间(比JIT)来优化。例如,gcc-O3正在进行大量扩展性优化,这是大多数JIT JVM无法承受的。因此,gcc-O3通常会产生非常

我最近了解到,JIT编译器用于将与平台无关的代码编译为本机代码。JVM和.net运行时环境使用它,以获得更好的性能和显著减少编译时间。我的问题是,为什么直接编译成本机代码的普通编译器(如c编译器)也不能作为JIT?JIT编译器的使用是否有限制或规范?

像大多数C编译器(如GCC)一样,提前优化编译器可能会产生比JIT编译器更好的机器代码。但是提前编译器通常需要更多的时间(比JIT)来优化。例如,
gcc-O3
正在进行大量扩展性优化,这是大多数JIT JVM无法承受的。因此,
gcc-O3
通常会产生非常高效的机器代码(比JVM好得多)


然而,在某些情况下,JIT技术可能会提供更好的代码,因为它能够考虑一些提前编译器未知的动态属性。例如,JIT编译器可以考虑在某些特定的调用站点上,调用的参数通常有一个给定的类(该类取决于调用站点,并且是动态学习的)。

现代javascript实现也会进行JIT,一些PHP、Python和Ruby实现(至少)也是如此。然而,JIT的诀窍在于它们是一个相对较新的开发,使它们工作的部分原因是您依赖于最终用户机器上的某种类型的框架或运行时,该框架或运行时能够对该机器和应用程序实例进行正确的优化


对于希望接近计算机“裸机”的语言,依赖额外的抽象层并不总是有意义的。

JIT有其优点和缺点。如果您将软件部署到许多不同的PC上,JIT会非常有用,因为JIT编译器可以检测如何优化每个特定平台的代码

问题是,JIT增加了另一个必须采取的步骤,才能首先执行软件:首先必须将其编译为IL,然后再编译为机器代码,这意味着额外的性能开销。但是,这种从IL到机器代码的转换只需要在软件第一次运行时完成,因此每次后续调用都会快得多


因此,基本上(作为经验法则),您可以说:如果软件是一个长期运行的过程,那么使用JIT通常是好的,如果软件的生命周期较短,那么最好使用本机代码。

我可以想到以下几个原因:

  • 预编译的二进制文件可以使用高级别的优化,这需要几天的时间才能实现最佳性能,这在JIT编译器中是不需要的

  • 初始JIT编译可能需要比直接解释更长的时间,在常见情况下的后续运行中存在不明显的差异

  • JIT编译可以占用其他运行时进程所需的用户资源(我没有看到很多3d JIT编译的游戏)

  • 预编译的解释器,如果编写效率高,可以达到接近足够的速度,同时允许用户即时修改源代码而不会降低性能

随着x86指令集的差异以及arm、mips等的日益广泛使用,商业软件的情况开始发生变化。。。在消费类设备以及不同的操作系统中。当您增加JIT编译器在视频卡上使用本机代码的能力(也有很大差异)时,尝试分发针对每个独特组合优化的编译版本就变得越来越不合理了。在某种程度上,一个能够访问所有cpu和gpu的合理JIT编译器的性能将优于一个编译后的等价编译器,后者仅限于(例如)x86的一个子集


经常被问到的一件事是,你是否可以只分发字节码。。。差不多,但不完全一样。它适用于java,因为它被设计为虚拟的,因此不需要像libc那样担心端性和其他硬件问题,也不需要担心每个体系结构(所有在虚拟机中实现的)的自定义汇编语言位,从而真正获得坚实的基础,您需要实现一个为JIT设计的基本libc(由于其简化的代码和许可证,可能基于musl libc)

编译器的目的通常是生成机器代码,所以我对您的上述问题感到惊讶。。。。你认为编译器会产生什么?我对你答案中“更好”的部分很感兴趣,但是JIT本质上涉及IL和本机代码分层吗?我的问题是,它不能用于简单的母语编译器吗?我不同意经验法则。许多长时间运行的服务器软件(如数据库系统,如mysql,或复杂的数字代码,如计算DNA或核反应堆的CPU时间长达数周)从提前优化编译器中获益匪浅。是的,这就是我称之为经验法则的原因。请阅读维基百科上“经验法则”的定义:JIT是否总是涉及额外的抽象层?是的,这一层是JIT的全部要点。如果您避开该层(例如使用ngen.exe),则不再使用JIT。看见