Reputation: 1139
I've been exploring compiling Perl programs as a way to improve the initial startup time on a complex Perl CGI program. @Rurban's detailed overview was very helpful to me. Compiling my main process script yields a faster startup time using perlcc -o launcher launcher.fpl
. The resultant process is at least 20% faster -- not overwhelming, but still meaningful.
Why am I trying to compile as oppose to simply optimize further? I've spent months using Devel::NYTProf
to catch inefficient code, so I believe I've attacked most of the low hanging optimization fruit. The code is fast, once loaded and it is run via mod_fcgi
FastCGI, so it stays persistently loaded. However, if it should happen to crash or if FastCGI needs to spawn a new process (either because the previous one has hit its maximum request level or there is enough demand that another worker is needed), the slow load time rears its ugly head. The first request on a new process may take 1-1.5 seconds, while subsequent requests clock in at under 200ms.
The issue: a lot of the program is in the form of Perl modules that the core "loader" dynamically loads based on what it is doing. The module loaded for the front page of my site is one of the slowest, for example. So, it stands to reason, some of the most important optimization would come from compiling those modules. However, using both perlcc -B Front.pm -o Front.pmc
and perl -c Front.pm
, I get an unhelpful segfault when I try to run the program:
[root@server code]# ./launcher.fpl
Segmentation fault (core dumped)
The compilation process provides no debug messages to suggest a problem. (To be clear: to keep things simple, in this example, launcher.fpl is not compiled, just straightforward Perl.) If I remove the pmc file so that launcher.fpl can load the uncompiled module once again, it loads without errors.
I've also tried:
perl -MO=Bytecode,-m,-oFront.pmc Front.pm
Which seems to work slightly better but produces this error when I try to run the program:
[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 line 117 is where the Front.pm(c) module is required:
state $moduleFront = require Front;
This leads to two main questions: (1) am I going about this the right way to begin with and (2) if I am not on the wrong path entirely, is there a way to debug why my module segfaults if it is compiled?
Upvotes: 1
Views: 248
Reputation: 385789
if it should happen to crash or if FastCGI needs to spawn a new process, the slow load time rears its ugly head.
That's not true; it should simply be a fork, which is instantaneous. (And even if it did take time, it would be between requests and not while a client is waiting.) There is no problem to solve here.
If you aren't forking, this is where you should be focusing your efforts. With forking, you can preload the modules your scripts use. The net effect over CGI is not only avoiding the time needed to load perl
but the time needed to execute the modules as well.
Upvotes: 1