pperl 0.6.23 - 吐槽、REPL 与速度
内容提要
pperl 0.6.23 发布,新增内置 REPL 交互模式 ipps,支持变量跨行保留、Tab 补全和 :jit 查看循环编译。作者因不满 GPL-3,用 Rust 重写约 1.5 万行 readline 替代品。性能上,MIME::Base64、Digest::SHA 和 Encode 的原生实现显著快于 Perl 的 XS 版本,多线程下最高快数十倍。
延伸解读
许可证争议与自研行编辑器的动机
作者对 GPL-3 和 AGPL 的传染性条款表示不满,认为其阻碍软件采用。为避免 pperl 因动态链接 GNU Readline 而被要求以 GPL-3 发布,作者用 Rust 从手册 clean-room 重写了约 1.5 万行 readline 替代品,并通过 5866 个测试用例验证与 GNU Readline 8.3 行为一致。这使 pperl 不再依赖 libreadline、libhistory 或 curses,也避免了许可证冲突。
内置 REPL 的实用特性与限制
pperl 0.6.23 新增交互模式 ipps,支持变量、子程序、模块和 pragma 跨行保留,Tab 补全基于会话内容,:jit 可查看循环是否被 JIT 编译。但需注意,$1、local 和 my sub 等词法作用域仅限当前行,与文件中的行为不同。该 REPL 内置于二进制,无需额外安装 CPAN 模块,降低了使用门槛。
性能提升的适用范围与解读
MIME::Base64、Digest::SHA 和 Encode 的原生实现显著快于 Perl 的 XS 版本,多线程下最高快数十倍。但部分提升源于工作负载差异:例如 Encode 对 latin1 字节串的编码,perl 需先转为 UTF-8,而 pperl 直接复制,因此 14 至 68 倍的差距不应简单视为编码速度提升。整体几何平均为单线程 3.9 倍、多线程 5.0 倍,且所有结果与 XS 一致。
Q&A
pperl 0.6.23 新增的 REPL 交互模式叫什么?怎么启动?
pperl 0.6.23 新增的 REPL 交互模式叫 ipps,是“interactive PetaPerl shell”的缩写。可以通过运行 `pperl --shell` 启动,或者创建一个符号链接 `ln -s "$(command -v pperl)" ~/bin/ipps` 后直接运行 `ipps`。
ipps 的 REPL 和 Perl 自带的调试器有什么不同?
Perl 自带的 `perl -de 0` 调试器每一行都在自己的作用域中求值,所以上一行定义的 `my $x` 在下一行就消失了。而 ipps 的 REPL 中,一行就是一段 Perl 代码,编译运行后留下的东西会保留:my 变量、子程序、加载的模块、pragmas 和当前包都会跨行保留。
ipps 的 :jit 命令有什么作用?
:jit 命令用于运行一行代码并报告 JIT 在此期间做了什么,例如显示编译了多少个循环、新看到了多少个循环等。它让用户可以在提示符下快速检查某个循环是否被 JIT 编译,而不需要像以前那样用 --jit-stats 运行整个程序。
pperl 为什么用 Rust 重写了一个 readline 替代品?
因为 GNU Readline 从 6.0 版本开始采用 GPL-3 许可证,按照 FSF 的解释,pperl 在运行时动态加载 libreadline 会导致 pperl 也被 GPL-3 覆盖。pperl 作者不同意这种解释,但更愿意专注于软件开发而不是与 FSF 争论法律问题,所以用 Rust 从 readline 手册出发净室重写了约 15,000 行代码,不依赖任何 GPL 源码。
pperl 0.6.23 中 MIME::Base64 的性能比 Perl 的 XS 版本快多少?
在 256 MiB 输入下,pperl 的 MIME::Base64 比 perl 5.44 的 XS 版本快很多:编码 MIME 行时,单线程快 3.1 倍,默认多线程快 7.8 倍;解码 MIME 行时,单线程快 9.9 倍,默认多线程快 19.3 倍。无换行编码时,单线程快 3.9 倍,多线程快 7.7 倍;无换行解码时,单线程快 10.9 倍,多线程快 18.7 倍。
pperl 的 Encode 模块在单字节编码上为什么比 Perl 快那么多?
pperl 的 Encode 模块对单字节编码使用两个平面表,并针对 ASCII 连续段进行复制优化,同时将大转换拆分到多个核心上并行处理。对于已经是 latin1 或纯 ASCII 的字节字符串,pperl 直接复制而不需要像 Perl 那样先转换为 UTF-8,因此速度提升显著,最高可达 68 倍。