我正在为一项研究项目做功能调查。
请列举一个难以优化的主流语言或语言特性,并解释这个特性是否值得付出代价。或者,通过轶事证据来反驳我的理论。在有人指出这是主观问题之前,我要求列举具体的语言或特性示例,以及对这些特性进行优化的想法,或者重要的特性,我还没有考虑到的。此外,任何证明我理论正确或错误的实现参考都可以。
以下是我认为难以优化的一些特性和理论(其中一些理论未经测试,仅基于思维实验):
1) 运行时方法重载(也称多方法分派或基于签名的分派)。当与允许运行时重新编译或添加方法的功能相结合时,它是否难以优化?或者说,无论如何都很难优化?调用站点缓存是许多运行时系统的常见优化方式,但多方法添加了额外的复杂性,使得内联方法变得不太实用。
2) 类型变形/变体(也称为基于值的类型而非基于变量的类型) 当你不知道某个东西的类型是否会在基本块中发生变化时,传统的优化方法就无法应用。与多方法结合使用时,内联必须小心谨慎地进行,可能仅针对被调用方的一定大小阈值。也就是说,很容易考虑内联简单的属性获取(getter/setter),但是内联复杂的方法可能导致代码膨胀。另一个问题是我不能只将变体分配给寄存器并将其JIT为本机指令,因为我必须携带类型信息,或者每个变量都需要2个寄存器而不是1个。在IA-32上,这很不方便,即使在x64的额外寄存器下得到改善。这可能是动态语言最喜欢的特性之一,因为它从程序员的角度简化了许多东西。
3) 第一类continuation - 有多种实现方式,我已经在两种最常见的方法中都实现了它们,一种是堆栈复制,另一种是实现运行时使用continuation传递风格、仙人掌堆栈、写时复制堆栈帧和垃圾回收。第一类continuation存在资源管理问题,即我们必须保存所有内容,以防恢复continuation,而且我不知道是否有任何语言支持离开具有“意图”的continuation(即“我不会再回来这里了,所以你可以舍弃这个世界的副本”). 通过编程实现线程模型和contination模型,我知道两者都可以完成同样的任务,但continuation的优雅性对运行时产生了相当大的复杂性,并且可能会影响缓存效率(使用continuations和协程后堆栈的局部性更容易发生变化)。另一个问题是它们不会映射到硬件。优化continuation是优化较少出现的情况,正如我们所知,通常情况应该快速处理,而较少出现的情况应该是正确的。
4) 指针算术和能力掩码指针 (存储在整数等中)。必须提一下,但我可以很容易地没有它。
我的感觉是许多高级特性,特别是在动态语言中,不适用于硬件。微处理器实现背后有数十亿美元的研究支持芯片优化,然而语言特性的选择可能使许多这些特性边缘化 (如缓存、别名堆栈到寄存器、指令并行性、返回地址缓冲区、循环缓冲区和分支预测等特性)。微功能的宏应用并不一定像一些开发人员所认为的那样实用,而且在VM中实现许多语言最终将本机操作映射到函数调用中(即,语言越动态,我们就必须在运行时查找/缓存,不能假设任何内容,因此我们的指令混合比传统静态编译代码包含更高比例的非本地分支),我们唯一能够真正进行JIT的是非动态类型的表达式评估和常量或立即类型的操作。我的直觉是,由于这个原因,对于某些语言,使用字节码虚拟机和JIT核心或许并不总是合理的。
欢迎您的回答。