Compiler construction 无法理解有关编译器的语句';优化

Compiler construction 无法理解有关编译器的语句';优化,compiler-construction,runtime,compile-time,vm-implementation,Compiler Construction,Runtime,Compile Time,Vm Implementation,我对VM在运行时和编译时的优化感兴趣。我的想法是,优化在编译时是最有效和最简单的 然而,在某些情况下,我的想法似乎是错误的。这一点在中国很明显 [O] 当在运行时由一个聪明的人执行时,优化通常更容易 虚拟机 为什么VM在运行时执行优化比在编译时执行优化更容易?简短回答:因为在运行时更容易识别和分析热点-程序中使用时间最多的部分 长答案: 如果开始以解释模式运行代码,虚拟机可以计算代码的不同部分使用的频率和时间。这些部分可以得到更好的优化 采用嵌套的if-then-else子句。更少的布尔检查需要

我对VM在运行时和编译时的优化感兴趣。我的想法是,优化在编译时是最有效和最简单的

然而,在某些情况下,我的想法似乎是错误的。这一点在中国很明显

[O] 当在运行时由一个聪明的人执行时,优化通常更容易 虚拟机


为什么VM在运行时执行优化比在编译时执行优化更容易?

简短回答:因为在运行时更容易识别和分析热点-程序中使用时间最多的部分

长答案:

如果开始以解释模式运行代码,虚拟机可以计算代码的不同部分使用的频率和时间。这些部分可以得到更好的优化

采用嵌套的if-then-else子句。更少的布尔检查需要更少的运行时间。如果优化零件的路径(执行频率更高),则可以获得更好的总体运行时间

另一点是,在运行时,您可以做出编译时不可能的假设。Java VM实例以服务器模式虚拟方法内联——只要只加载一个实现这些方法的类。如果在编译时执行,那么这将是不安全的。如果加载了另一个类,JVM会再次对代码进行去优化,但这种情况通常不会发生

此外,在运行时,用户更了解程序运行的机器。如果你有一台拥有更多寄存器的机器,你可以使用它们。同样,如果在编译时执行,这是不安全的

有一点要说:运行时优化也有缺点。最重要的是:优化的时间被添加到程序的运行时中。而且它更复杂,因为您必须编译程序的各个部分并执行它们。虚拟机中的bug非常关键。想想编译器,有时会崩溃——你可以再次编译,一切都很好。如果虚拟机有时崩溃,这意味着您的程序有时会崩溃。不太好


作为结论:您可以在运行时进行所有优化,这在编译时是可能的。。。还有一些。您有关于程序、程序执行路径和程序运行的机器的更多信息。但是您必须考虑运行优化所需的时间。此外,在运行时执行此操作更为复杂,故障比在编译时更为相关。

因为在运行时,您有额外的信息:机器的运行方式、进程的内存限制,可能最重要的是,执行什么代码以及执行频率


这些功能允许您进行编译时无法进行的运行时优化。

因为运行时有更多可用信息。例如,确切的CPU、操作系统和其他环境细节是已知的。这些信息对优化应该如何进行有影响。

虚拟机有完整的程序代码,而编译器通常只有部分代码,因为不同的翻译单元是分开翻译的。因此,虚拟机有更多的数据用于分析。

虚拟机可以收集统计数据以进行优化,数据库也可以根据您的使用情况进行优化。

连续保存统计数据和检查不变量也会增加编译或解释片段的执行时间。如果你不能很快很好地进行优化,那就不用麻烦了。我不认为在运行时而不是编译时获得更好的结果更容易。考虑到一个好的实现的复杂性,我认为这更加困难


与“足够好的优化编译器生成比人类更好的程序集”这一常见误解非常相似,足够聪明的VM可能需要非常聪明才能执行得更快。

需要认识的是,允许运行时优化的并不是VM的概念,事实上,许多虚拟机并不丢弃原始的程序元数据,而是内置了反射功能。更合适的术语是“运行时库”可以比静态优化做得更好;这适用于非虚拟机语言,如C。

我认为Steve Yeggie的意思是“更容易获得更好的结果”,而不是“更容易做”,这就是我认为您的解释。毕竟,我想象重新安排一个程序在运行时比在编译时更难。“你可以在运行时做编译时可能做的每一个优化”——我不相信。配置文件引导优化器可以重新排列对象中数据成员的顺序,例如,改进引用的位置或将最常用的对象移动到偏移量0。如果内存中已经有实际的对象,这几乎是不可能的。现代垃圾收集器总是重新排列内存中的对象以减少碎片。要做到这一点,必须重写所有引用/指针(或者使用一些巧妙的间接方法)。在这种情况下,重新排列数据成员似乎并不复杂。但我必须承认,我不知道有哪一个虚拟机能够真正做到这一点。这其实非常简单,特别是因为使用mark sweep垃圾收集的虚拟机将定期遍历整个对象树。同样,运行时是赢家,因为您可以看到哪些字段真正是在一起访问的,而不是在一个很少调用的方法中。(注意:我不知道.Net或Java虚拟机是否真的做到了这一点,我个人对此表示怀疑)@Mnementh:对最后一句话的评论:你的意思是运行时的优化比编译时更复杂,错误在运行时比编译时更相关。@Masi:faults更相关,因为编译器上的错误不一定会破坏已编译的程序。虚拟机上的故障是在虚拟机上执行的程序的故障。Yup-编译器通常不能利用SSE3