in reply to Re^7: appending to html at beginning (don't use CGI.pm)
in thread appending to html at beginning

If you mean speed-wise, you may be right

I do and I am. :-)

About a year ago a new project was starting and it was unclear at that point whether it would be better as a traditional CGI system or using some sort of persistent back-end. Having read of the joys of Plack this sounded to me like an ideal use for it - code the system with Plack and we could switch seamlessly between normal CGI and a persistent application.

Obviously the first thing to do was to put together a prototype to prove the concept. I wrote a little "hello world" script using Plack (it may even have been lifted directly from the docs) and managed to get it running without much bother as a persistent job. Then I switched over the front end and had it running as traditional CGI. That's when I noticed the speed issue.

We all expect a CGI script to be slower than a persistent system (that's why there's an F in FCGI after all) but this was noticeably slower. And it seemed to me to be a lot slower than many of the other CGI scripts I would normally use. And it wasn't even doing anything other than respond with "Hello World".

So I did the natural thing and benchmarked it as a traditional CGI both with Plack and without. It turned out that using Plack slowed down the traditional CGI by about a factor of 6.

It was decided that this was just too much of a penalty so instead of using Plack I wrote a frontend which had a very simple loading routine that could be called either from CGI or from an FCGI implementation. This added no measurable difference to the execution time of the plain CGIs and meant that we could easily switch between the two approaches as the need arose.

TL;DR: Plack is a nice idea but while it technically can be used for traditional CGI scripts beware that the penalty is a big slowdown.

  • Comment on Re^8: appending to html at beginning (don't use CGI.pm)

Replies are listed 'Best First'.
Re^9: appending to html at beginning (don't use CGI.pm)
by Your Mother (Archbishop) on Feb 27, 2017 at 13:38 UTC

    A factor of 6 sounds like a broken benchmark. A plack wrapper is not doing so much that much that it makes sense it would be 600% slower. Though perhaps there is something wonky/unexpected in the CGI handler. Do you have your benchmark on github or someplace to share?

      I couldn't find the original scripts (it was a good while ago and the point was proven then) so I've knocked up these scripts today which follow the same principle. If you can point out the errors in what I've done that would be most helpful.

      Firstly, here's the trivial non-plack CGI:

      #!/usr/bin/perl use strict; use warnings; use CGI::Lite; my $cgi = CGI::Lite->new; $cgi->parse_form_data; print "Content-Type: text/plain\n\n"; $cgi->print_data; exit;

      Here's the equivalent PSGI:

      use strict; use warnings; use Plack::Request; my $app = sub { my $env = shift; my $req = Plack::Request->new($env); my %params = %{$req->parameters}; my $body = ''; while (my ($k, $v) = each %params) { $body .= "$k = $v\n"; } my $res = $req->new_response; $res->status (200); $res->headers ({ 'Content-Type' => 'text/plain' }); $res->body ($body); $res->finalize; }

      And finally the wrapper to turn the PSGI into a CGI:

      #!/usr/bin/perl use strict; use warnings; use Plack::Loader; my $app = Plack::Util::load_psgi("light.psgi"); Plack::Loader->auto->run($app);

      To turn this into a "real" test I've run these through Apache with both client and server on the same host (ie. no network issues). The 2 cgi scripts were called with a single key-value pair in the query string (foo=bar, since you ask) and produced the same content as a result. Each script was called 11 times (1 as PoC and then another 10)

      The timings come from the apache log (with %D) and are as follows (all values are microseconds).

      Normal CGICGI through Plack
      Maximum2137193761
      Minimum1249480521
      Mean1499986481

      So, looking at the mean request time the plack version is 5.77 times slower than the plain CGI.

      Now, these are small samples and are wallclock times so YMMV and I encourage you to re-run the tests on your own platforms to see how they compare but this crude example reflects pretty closely what I originally saw and is enough of a penalty to be avoided (for me).

        Thanks for following up. I should point out this is the opposite of what I was talking about in the other thread when I said that CGI should use PSGI as its interface layer. This is, or flavors of it, is what I meant–

        use strictures; use Plack::App::WrapCGI; Plack::App::WrapCGI->new(script => "./my.cgi")->to_app;

        There is zero functional/feature/middleware benefit to going the other way: PSGI->CGI.

        You’re timing webserver responses… it’s hard to guess what’s up there. It’s also hard to measure such a trivial use meaningfully (it is like benchmarking “hello world”). I just sank about 45 minutes into trying to do a pure backend/perl benchmark but I’m having trouble getting part of it to act right and I’m outta gas and IQ.

        And how many workers does apache have? I think thats what you're seeing

        This is what I tried, can't get simpler/faster than this, cgi-bin/printenv.pl

        This one does more (loads modules) so it should be slower , dumpenv.psgi started with  plackup -l 127.6.6.6:80 dumpenv.psgi  2>2 1>1

        Then see whats faster

        for ( 1 .. 10 ) { cmpthese( 1000, { 'psgi' => q{ # LWP::Simple::get('http://127.0.0.1:5000/'); LWP::Simple::get('http://127.6.6.6:80/'); qw//; }, 'apache2cgi' => q{ LWP::Simple::get('http://localhost/cgi-bin/printenv.pl'); qw//; }, } ); }

        I tried it a bunch of times, and psgi is faster "half" the time (ok 4/10 or 3/10)

        So is apache "cgi" or psgi faster?

        My Apache is configured with ThreadsPerChild 4 -- not sure how many actual workers that is on my machine, but I see two apache processes ... one has 1 thread the other has 6, so 6 or 7 workers?

        And psgi still wins 3/10 times? How does that make apache faster?

        But yeah maybe the LWP is skewing the benchmark or .... something I dont understand

Re^9: appending to html at beginning (don't use CGI.pm)
by haukex (Archbishop) on Feb 04, 2017 at 13:15 UTC

    Hi hippo,

    Thanks very much for the info, that's good to know! If it wasn't obvious yet, I haven't used Plack in a traditional CGI environment very much :-) I try to use persistent processes as much as I can nowadays.

    Regards,
    -- Hauke D