Hacker News 中文摘要

RSS订阅

将Ruby编译为机器语言 -- Compiling Ruby to Machine Language

文章摘要

作者正在编写《Ruby Under a Microscope》的新版本,涵盖Ruby 3.x特性,重点介绍了YJIT和ZJIT编译器的工作原理。书中详细解析了Ruby代码如何被编译为机器语言,包括方法调用计数、块编译、分支存根等技术细节,并展示了YJIT如何优化代码执行。作者对Ruby团队在运行时性能提升方面的工作表示赞赏。

文章总结

将Ruby编译为机器语言

我正在着手编写《Ruby Under a Microscope》的新版本,该书将涵盖Ruby 3.x的内容。由于是利用业余时间进行这项工作,预计需要较长时间完成。如果您有兴趣,可以留言或发送邮件给我,待书完成后我会通知您。

以下是第四章关于YJIT和ZJIT的全新内容节选。这部分内容刚刚完成,对我来说,学习JIT编译器的工作原理并重温Rust技能是件非常有趣的事。同时,看到Shopify的Ruby团队及其他贡献者为提升Ruby运行时性能所做的卓越工作也令人振奋。

第四章:将Ruby编译为机器语言

本章主要探讨Ruby代码的解释执行与编译执行,重点介绍了YJIT和ZJIT这两种即时编译器的工作原理。

方法调用计数

YJIT通过统计每个函数或块的调用次数来识别热点代码。当调用次数达到特定阈值时,YJIT会暂停程序执行,将该部分代码转换为机器语言。此后,Ruby将直接执行机器语言版本而非原始的YARV指令。

YJIT通过在YARV指令序列附近保存内部计数器来跟踪调用次数。例如,在图4-5中,YJIT为代码块保存了两个值:jitentry(初始为空,后续将指向生成的机器指令)和jitentry_calls(调用计数器)。当计数器达到阈值(小型程序默认为30,大型程序如Rails为120)时,YJIT触发编译过程。

YJIT代码块

YJIT将生成的机器指令保存在"YJIT块"中。这些块不同于Ruby块,每个YJIT块对应一小段YARV指令的机器语言翻译。通过这种方式,YJIT能生成更优化的代码,并避免编译程序不需要的部分。

例如,在图4-6和图4-7中,YJIT首先将getlocalWC1指令编译为机器语言并创建新块,随后继续编译getlocalWC0指令并扩展该块。图4-8展示了该块内部的具体机器指令(如ARM64架构下的寄存器操作)。

分支存根

当遇到类型不确定的操作(如加法运算)时,YJIT采用"分支存根"技术。由于机器指令对类型有严格要求,YJIT不会预先分析所有可能的类型组合,而是等待实际运行时观察具体类型。

如图4-9所示,当遇到opt_plus指令时,YJIT会创建分支存根。如果后续运行中发现操作数为整数,YJIT会生成相应的整数加法指令;若发现其他类型,则可能生成不同的代码或保持解释执行。这种延迟编译策略显著提高了编译效率。

(注:本文保留了核心的技术细节,删减了部分实验性内容和次要说明,确保主题的连贯性。)

评论总结

评论总结:

  1. 对《Ruby Under a Microscope》及其作者的积极评价
  • 高度赞赏作者Pat及其作品:"His first Ruby under a Microscope book...are amazing and a major source of inspiration"(评论1)
  • 书籍实用性强:"using that knowledge was able to have fun with some CTFs years ago"(评论2)
  1. 对新版书籍的期待
  • 计划购买新版:"I will sure as heck buy this new version"(评论2)
  • 新读者兴趣浓厚:"I'll have to pick up a copy...when the new version comes out"(评论3)
  1. 关于Ruby实现历史的讨论
  • 提到MacRuby的LLVM实现:"MacRuby used to compile to native code...using LLVM"(评论3)
  • 指出技术转向:"but I guess Apple moved to Swift instead"(评论3)

注:所有评论均未显示评分(None),但整体呈现积极倾向。评论者包括长期读者、技术爱好者和潜在新读者。