为更快的 FastCGI 操作编译 Perl

Compiling Perl for Faster FastCGI Operation

我一直在探索编译 Perl 程序,以此来缩短复杂 Perl CGI 程序的初始启动时间。 @Rurban's detailed overview 对我很有帮助。使用 perlcc -o launcher launcher.fpl 编译我的主进程脚本会产生更快的启动时间。由此产生的过程至少快了 20% -- 不是压倒性的,但仍然有意义。

为什么我要尝试编译而不是简单地进一步优化? 我花了几个月的时间使用 Devel::NYTProf 来捕获低效代码,所以我相信我已经攻击了大部分低挂的优化果实。代码很快,一旦加载,它是 运行 通过 mod_fcgi FastCGI,所以它保持持久加载。然而,如果它碰巧崩溃或者 FastCGI 需要生成一个新进程(要么是因为前一个进程达到了它的最大请求级别,要么是因为有足够的需求需要另一个工作人员),缓慢的加载时间就会抬起头来。新进程的第一个请求可能需要 1-1.5 秒,而后续请求的时间不到 200 毫秒。

问题: 很多程序都采用 Perl 模块的形式,核心“加载器”根据其正在执行的操作动态加载这些模块。例如,为我网站的首页加载的模块是最慢的模块之一。因此,按理说,一些最重要的优化将来自编译这些模块。但是,同时使用 perlcc -B Front.pm -o Front.pmcperl -c Front.pm,当我尝试 运行 程序时出现无用的段错误:

[root@server code]# ./launcher.fpl
Segmentation fault (core dumped)

编译过程没有提供任何调试消息来提示问题。 (要清楚:为了简单起见,在这个例子中,launcher.fpl 是 编译的,只是简单的 Perl。)如果我删除 pmc 文件以便 launcher.fpl 可以再次加载未编译的模块,加载没有错误。

我也试过:

perl -MO=Bytecode,-m,-oFront.pmc Front.pm

这似乎工作得稍微好一点,但是当我尝试 运行 程序时产生这个错误:

[root@server cgi-bin]# ./launcher.fpl
Number found where operator expected at /home/user/www/cgi-bin/Front.pm line 1, near "multi0.12"
Local: Sat Jul 10 14:58:18 2021: Dying from error.; At file: /home/user/www/cgi-bin/Front.pm; line: 1; id: 
Error: Unrecognized character \x08; marked by <-- HERE after ulti<-- HERE near column 36 at /home/user/www/cgi-bin/Front.pm line 1.
Compilation failed in require at /home/user/www/cgi-bin/Loader.pm line 117.

Loader.pm 第 117 行是需要 Front.pm(c) 模块的地方:

state $moduleFront = require Front;

这引出了两个主要问题:(1) 我开始的方式是否正确,以及 (2) 如果我没有完全走错路,有没有办法调试我的模块出现段错误的原因如果编译成功?

if it should happen to crash or if FastCGI needs to spawn a new process, the slow load time rears its ugly head.

那不是真的;它应该只是一个叉子,它是即时的。 (即使确实需要时间,也应该是在请求之间,而不是在客户端等待期间。)这里没有问题要解决。

如果您不进行分叉,那么这就是您应该集中精力的地方。通过分叉,您可以预加载脚本使用的模块。 CGI 的最终效果不仅避免了加载所需的时间 perl,而且还避免了执行模块所需的时间。