Mérés – CGI (bash/perl/C), FastCGI vagy mod_perl? Melyik a gyorsabb? :)

És akkor jöjjön az igazság órája! Nézzük meg, hogy az előző két fejezet kis webalkalmazásai közül melyek a leggyorsabbak. Természetesen egy komplex webalkalmazás mérése beszédesebb volna, de reményeim szerint 1000 mérésből a curl programcsomag segítségével egy egyszerű script segítségével is ki tudjuk deríteni, hogy mi a helyzet.

Kiindulás. A rendszer load-ja (leterheltsége) az utolsó 5 percben 1,19. Alacsony. Ez ahogy később kiderült, nem is válltozik. 🙂 És igen, a notebook 161 napja nem volt újraindítva. 🙂

gvamosi@gergo1:/var/www/perl$ uptime
 04:07:48 up 161 days,  5:02,  1 user,  load average: 1.68, 1.19, 1.02

Nézzük a mérést végző script-ünket!

#!/bin/bash

START=`date +%s.%N`
echo $START
for ((i=1;i<=1000;i++)); 
do 
	curl -s $1 2>&1> /dev/null
done
END=`date +%s.%N`
RUNTIME=$(echo "$END - $START" | /usr/bin/bc)
echo $END
echo $RUNTIME

Ez egy egyszerű script. Az időt méri, és a parancssorban kapott első paraméterre mint URL-re meghívja a curl parancs segítségével a webalkalmazásunkat.

MÉRÉS I. CGI, bash script. http://localhost/cgi-bin/counter.sh13,76 másodperc.

gvamosi@gergo1:~/Documents/http_meres$ ./1000times_curl.sh http://localhost/cgi-bin/counter.sh
1597372454.016087696
1597372467.780319906
13.764232210

MÉRÉS II. CGI, perl. http://localhost/cgi-bin/counter.pl16,75 másodperc.

gvamosi@gergo1:~/Documents/http_meres$ ./1000times_curl.sh http://localhost/cgi-bin/counter.pl
1597372699.883363458
1597372716.637874845
16.754511387

MÉRÉS III. CGI, natív C. http://localhost/cgi-bin/counter.cgi12,37 másodperc.

gvamosi@gergo1:~/Documents/http_meres$ ./1000times_curl.sh http://localhost/cgi-bin/counter.cgi
1597372832.246672103
1597372844.623081288
12.376409185

MÉRÉS IV. FastCGI, perl. http://localhost/cgi-bin/counter.pl.fcgi10,19 másodperc.

gvamosi@gergo1:~/Documents/http_meres$ ./1000times_curl.sh http://localhost/cgi-bin/counter.pl.fcgi
1597372942.444961716
1597372952.635298535
10.190336819

MÉRÉS V. mod_perl. http://localhost/perl/counter-mod_perl.cgi10,51 másodperc.

gvamosi@gergo1:~/Documents/http_meres$ ./1000times_curl.sh http://localhost/perl/counter-mod_perl.cgi
1597373028.237804238
1597373038.753424598
10.515620360

Látható, hogy bár igen egyszerű a webalkalmazás, csupán pár sor, a várható mérési eredményeket hozta. A leglassabb a sima perl CGI, gyorsabb a bash script illetve a natív C, míg a FastCGI illetve a mod_perl a leggyorsabbak. 🙂

És akkor egy (viszonylag régi) összehasonlító mérés a net-ről (https://stackoverflow.com/questions/382798/mod-perl-vs-mod-fastcgi). 🙂

cgi - 1200+ requests per minute
mod_perl - 6000+ requests per minute (ModPerl::PerlRun only)
fast_cgi - 6000+ requests per minute
mod_perl - 6000+ requests per minute (ModPerl::Registry)
servlets - 2438 requests per minute.

Megjegyzés: ez egy egyszerű tesztelési eljárás alapbeállításokkal (Apache) szerveroldalon, helyi gépen, 8GB memóriával, 4 magos processzorral és SSD háttértárral. Lehetne több szerverpéldányt indítani, párhuzamosítani, azaz egyszerre több kliensről tesztelni. Alapvetően idő és tárkorlátos minden számítástechnikai eljárás, szoftver, illetve program. Tehát CPU és memória/háttértár. A webes tesztekbe ezen kívül a hálózati sebesség is beleszámít(hat).

Egyszerű számláló FastCGI perl és mod_perl implementációban

A FastCGI abban különbözik a CGI-től, hogy amíg a CGI egy kérésre egy folyamatot hoz létre a szerveren, a FastCGI újbóli futásra képes, újbóli betöltődés nélkül, ezáltal több kérést tud kiszolgálni egységnyi idő alatt, tehát nagyobb teljesítményt lehet vele elérni. Részletek itt https://en.wikipedia.org/wiki/FastCGI.

Ha ilyet szeretnénk fejleszteni, először is installánunk kell az alapból nem telepített FastCGI Apache modul-t. Ez az alábbi módon lehetséges.

root@gergo1:~# apt-get install libapache2-mod-fcgid

Majd nézzük a /etc/apache2/mods-enabled/fcgid.conf configurációs file tartlamát.

<IfModule mod_fcgid.c>
  FcgidConnectTimeout 20

  <IfModule mod_mime.c>
    AddHandler fcgid-script .fcgi
  </IfModule>
</IfModule>

Ezután hozzuk létre az első, perl nyelvű counter.pl.fcgi programocskát a cgi-bin könyvtárunkban.

#!/usr/bin/perl

use FCGI;

my $count = 0;
my $request = FCGI::Request();

while($request->Accept() >= 0) {
    print("Content-type: text/html\r\n\r\n", ++$count);
}

Látható, hogy az FCGI kérés többször lefuthat. Ha ezt az oldalt pl. hétszer frissítjük böngészőben a http://localhost/cgi-bin/counter.pl.fcgi cím alatt, akkor egy 7-es számot fog kiírni. 🙂

Megjegyzem, ha nincs az FCGI modul telepítve a perl-en belül, akkor a cpan paranccsal tudjuk ezt megtenni. A CPAN a perl csomagkezelője https://www.cpan.org/.

Most nézzük a mod_perl implementációt is! Először is szükségünk lesz az Apache modulra.

root@gergo1:~# apt-get -y install libapache2-mod-perl

Ezután nézzük meg a /etc/apache2/conf-available/mod_perl.conf konfigurációs állományt.

# create new
# for example, set PerlRun mode under the "/var/www/perl"
PerlSwitches -w
PerlSwitches -T

Alias /perl /var/www/perl
<Directory /var/www/perl>
    AddHandler perl-script .cgi .pl
    PerlResponseHandler ModPerl::PerlRun
    PerlOptions +ParseHeaders
    Options +ExecCGI
</Directory>

<Location /perl-status>
    SetHandler perl-script
    PerlResponseHandler Apache2::Status
    Require ip 127.0.0.1 10.0.0.0/24
</Location>

Majd az “élesítő” parancsokat.

root@gergo1:~# a2enconf mod_perl
Enabling conf mod_perl.
To activate the new configuration, you need to run:
  systemctl reload apache2
root@gergo1:~# systemctl reload apache2

Végül írjuk meg a perl programunkat counter-mod_perl.cgi néven.

#!/usr/bin/perl

use strict;
use warnings;

print "Content-type: text/html\n\n";

my $a = 0;
&number($a);

sub number {
    my($a) = @_;
    $a++;
    print "number \$a = $a";
}

Ez a kis programocska a http://localhost/perl/counter-mod_perl.cgi cím alatt annyit ír ki, hogy number $a = 1. 🙂

A dokumentáció szerint (https://perl.apache.org/start/index.html) egy pici változtatással 100x-os sebességnövekedést érhetünk el a script-nél (https://perl.apache.org/start/tips/registry.html). Ezt meg is fogjuk mérni a következő fejezetben! 🙂

root@gergo1:~# vi /etc/apache2/conf-enabled/mod_perl.conf

Alias /perl /var/www/perl
<Directory /var/www/perl>
    AddHandler perl-script .cgi .pl
    # comment out PerlRun mode and add Registry mode like follows
    #PerlResponseHandler ModPerl::PerlRun
    PerlResponseHandler ModPerl::Registry
    PerlOptions +ParseHeaders
    Options +ExecCGI
</Directory>

root@gergo1:~# systemctl reload apache2

A mod_perl implementáció esetén az Apache szerverünk a kódot a memóriában tartja, és ott “fordítja”, ezért gyorsabb.