Ruby 如何构建并启用 YJIT 编译器,以及如何确认它已生效?
【免费下载链接】rubyThe Ruby Programming Language项目地址: https://gitcode.com/GitHub_Trending/ru/ruby
如果你希望在 CRuby 中获得 JIT 编译加速,需要做的不是安装某个现成组件,而是从源码构建一个启用 YJIT 的 Ruby 二进制,然后在运行时用--yjit选项(或环境变量、Ruby 代码)打开它,并确认它确实处于启用状态。YJIT 是内嵌在 CRuby 里的轻量级 Ruby JIT,目前支持 macOS、Linux 和 BSD,CPU 限 x86-64 与 arm64/aarch64(见 doc/jit/yjit.md)。本文按“准备依赖 → 构建 → 启用 → 验证”的顺序走完这条路径。
准备条件:构建工具链与 Rust 编译器
按 doc/contributing/building_ruby.md 和 doc/jit/yjit.md 的要求,构建一个带 YJIT 的 Ruby 需要:
- 构建 CRuby 的常规工具链:C 编译器;为 RubyGems 需要 OpenSSL(1.1.x / 3.0.x 或 LibreSSL)、libyaml(0.1.7 及以上)、zlib;
- 从 git 仓库构建时额外需要:autoconf(2.67 及以上)、ruby(3.1 及以上)、git(2.32 及以上);
- Rust 编译器
rustc,版本要求见 yjit/Cargo.toml 中的rust-version = "1.58.0",即 >= 1.58.0; - 可选:只有在以 dev/debug 模式构建时才需要 Rust 的
cargo。
文档的建议是:如果你不打算修改 YJIT 自身的 Rust 代码,直接用操作系统的包管理器安装rustc即可;要改 YJIT 源码时才建议使用 Rust 官方的一方安装方式。
获取源码并构建带 YJIT 的 Ruby
克隆ruby/ruby仓库并进入目录:
git clone https://github.com/ruby/ruby yjit cd yjitYJIT 的ruby二进制可以用 GCC 或 Clang 构建,可选三种配置模式。以下安装前缀$HOME/.rubies/ruby-yjit是文档示例中使用的路径,可按需改成自己的安装位置:
release 模式(文档推荐用于最高性能,配合 GCC):
# Configure in release mode for maximum performance, build and install ./autogen.sh ./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc make -j && make installdev(debug)模式,性能较低但包含扩展的 YJIT 统计信息,适合开发:
# Configure in lower-performance dev (debug) mode for development, build and install ./autogen.sh ./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc make -j && make installstats 模式,开启扩展统计但不带 dev 模式的慢速运行时检查:
# Configure in extended-stats mode without slow runtime checks, build and install ./autogen.sh ./configure --enable-yjit=stats --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc make -j && make installmacOS 上可能需要先通过 Homebrew 装好依赖,并用--with-opt-dir指明库的位置:
# Install dependencies brew install openssl libyaml # Configure in dev (debug) mode for development, build and install ./autogen.sh ./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --with-opt-dir="$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml)" make -j && make install如果想指定 C 编译器,在运行./configure之前设置:
export CC=/path/to/my/chosen/c/compiler其中/path/to/my/chosen/c/compiler是文档中的占位写法,替换为你实际编译器(如 gcc 或 clang)的路径。
构建完成后,文档给出的验证手段有两级:make btest运行 bootstraptest 目录下的快速测试;make -j test-all运行完整测试集。此外还有make yjit-check,文档描述为“运行快速检查以确认 YJIT 工作正常”。
启用 YJIT 的三种方式
YJIT 默认是禁用的(--yjit选项说明为“enable YJIT (disabled by default)”)。构建完成后有三种启用途径,可结合使用:
命令行选项:运行时加
--yjit,例如./miniruby --yjit myscript.rb。构建目录内的./miniruby可直接使用,也可以切换全局的ruby:chruby ruby-yjit ruby myscript.rb环境变量
RUBY_YJIT_ENABLE:适用于不方便给 Ruby 追加命令行参数的部署脚本。Ruby 代码:调用
RubyVM::YJIT.enable可以在应用启动完成后再开启 YJIT,文档指出这样可以避免编译初始化阶段用不到的代码。如果要携带--yjit-*调优参数但暂不启动 YJIT,可加--yjit-disable。
相关调优选项(默认值均引自文档):--yjit-mem-size=N为 YJIT 内存使用的软上限,单位 MiB,默认 128;--yjit-call-threshold=N为开始编译某函数所需的调用次数,默认 30(进程内 ISEQ 数达到 40,000 时提升到 120)。
确认 YJIT 已生效
文档给出了明确的验证方式:用RubyVM::YJIT.enabled?检查,或检查ruby --yjit -v的输出是否包含+YJIT字符串:
ruby --yjit -v ruby 3.3.0dev (2023-01-31T15:11:10Z master 2a0bf269c9) +YJIT dev [x86_64-darwin22] ruby --yjit -e "p RubyVM::YJIT.enabled?" true ruby -e "RubyVM::YJIT.enable; p RubyVM::YJIT.enabled?" true第一行是文档示例输出(具体版本号、提交号和平台串会因你的构建而异),判断依据是行内出现+YJIT;后两个示例输出true表示 YJIT 已成功启用。
确认“编译确实在发生”而不只是“开关已打开”,文档提供了三个进一步的手段:
--yjit-stats:程序执行结束后打印编译与运行统计(有运行时开销);也可以--yjit-stats=quiet只采集不打印,通过RubyVM::YJIT.runtime_stats读取。统计中的:ratio_in_yjit表示由 YJIT 执行的 YARV 指令占比,文档提到理想值应尽量接近 99%,调大--yjit-mem-size通常有助于提高这个比例;--yjit-log[=file|dir]:记录编译事件。不指定文件时,应用退出时把最近 1024 条日志打印到 stderr;--yjit-log=quiet则在环形缓冲区中收集,通过RubyVM::YJIT.log访问;- 反汇编查看某个方法的机器码:在脚本里加
puts RubyVM::YJIT.disasm(method(:method_name)),把method_name换成你的方法名。文档提醒:如果该方法尚未被编译,就不会有任何机器码生成。
限制与边界
按 doc/jit/yjit.md 的说明,需要注意两点:
- 平台限制:YJIT 仅支持 macOS、Linux、BSD 上的 x86-64 与 arm64/aarch64,其他平台组合无法使用;
- 内存代价:因为 JIT 需要在内存中生成机器码并维护额外状态,启用 YJIT 后内存占用高于纯解释执行。上限可通过
--yjit-mem-size(默认 128 MiB,限制code_region_size + yjit_alloc_size总和)和--yjit-exec-mem-size(限制可执行内存块大小)调整;--yjit-code-gc自 Ruby 3.3 起默认禁用,打开后当可执行内存达到上限时丢弃全部机器码并重新编译,可以用更小的内存上限,但达到上限时可能有轻微性能下降。
完成构建与验证后,如果你的目标是让长驻 worker 真正吃到 YJIT 的收益,文档在“Performance Tips for Production Deployments”一节建议尽量让进程少重启、关注ratio_in_yjit;相关调优项(--yjit-mem-size、--yjit-cold-threshold等)完整列表见 doc/jit/yjit.md 的 Command-Line Options 部分。
【免费下载链接】rubyThe Ruby Programming Language项目地址: https://gitcode.com/GitHub_Trending/ru/ruby
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考