我一直在修补 Javascript 国际象棋引擎。是的,是的,我知道(轻笑),这不是那种事情的最佳平台。这有点像一个宠物项目,我很享受学术练习,并且对接近编译语言速度的挑战很感兴趣。Javascript 中还有其他一些古怪的挑战,比如缺少 64 位整数,这使得它不适合国际象棋,但也很有趣。
不久前,我意识到小心构造、函数参数等非常重要。在国际象棋编程中一切都很重要,但在 Chrome 中通过 Javascript 使用 JIT 编译器(V8 Turbofan)时似乎很重要。
通过一些痕迹,我看到了一些急切的 DEOPT,我无法弄清楚如何避免。
DEOPT 急切,地图错误
跟踪引用的代码:
if (validMoves.length) { ...do some stuff... }
跟踪直接指向 IF 条件的 validMoves.length 参数。validMoves 只是一个空数组 [] 或移动对象数组 [{Move},{Move},...]
空数组 [] 会启动 DEOPT 吗?
顺便说一句,我有很多懒惰和软 DEOPT,但如果我理解正确的话,这些并不是那么重要,只是 V8 在最终优化它之前如何围绕我的代码包装它的一部分;在 --trace-opt 中,具有软、惰性 DEOPT 的功能似乎最终会被 Turbofan 优化,并且从长远来看可能不会对性能造成太大影响。(就此而言,急切的 DEOPT 功能似乎最终也得到了重新优化。)这是一个正确的评估吗?
最后,我有时发现通过将显示 DEOPT 的函数分解为多个较小的函数调用,我获得了显着的性能提升。据此,我推断更大更复杂的功能难以优化,通过分解它们,较小的分隔功能正在被优化,从而为我提供了收益。这听起来合理吗?