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ű CGI számláló bash, perl és C nyelveken

Először is engedélyezzük a cgi modul-t az Apache webszerverünkben. Ez pár sor Debian 10.5 alatt root-ként (rendszergazdaként).

root@gergo1:/etc/apache2/mods-enabled# ln -s ../mods-available/cgi.load
root@gergo1:/etc/apache2/mods-enabled# ls -l
..
lrwxrwxrwx 1 root root 26 Aug 12 02:24 cgi.load -> ../mods-available/cgi.load
root@gergo1:/etc/apache2/mods-enabled# service apache2 reload

root@gergo1:/etc/apache2/conf-enabled# ls -l
..
lrwxrwxrwx 1 root root 36 Aug 28  2017 serve-cgi-bin.conf -> ../conf-available/serve-cgi-bin.conf

Nézzük a serve-cgi-bin.conf konfigurációs file tartalmát!

<IfModule mod_alias.c>
        <IfModule mod_cgi.c>
                Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>

        <IfModule mod_cgid.c>
                Define ENABLE_USR_LIB_CGI_BIN
        </IfModule>

        <IfDefine ENABLE_USR_LIB_CGI_BIN>
                ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
                <Directory "/usr/lib/cgi-bin">
                        AllowOverride None
                        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                        Require all granted
                </Directory>
        </IfDefine>
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Látható, hogy a /usr/lib/cgi-bin könyvtárban kell létrehozzuk a számlálóinkat bash, perl és C nyelveken. Nézzük az elsőt bash shell script nyelven!

#!/bin/bash

printf "Content-type: text/html\n\n"
let COUNTER++
printf "$COUNTER\n"

És akkor teszteljük le parancssorból, majd web-en!

gvamosi@gergo1:/usr/lib/cgi-bin$ chmod +x counter.sh 
gvamosi@gergo1:/usr/lib/cgi-bin$ ./counter.sh 
Content-type: text/html

1

Látható, hogy 1-et ír ki, ha parancssorban futtatjuk.

Ha megnézzük weben is a http://localhost/cgi-bin/counter.sh cím alatt, ugyanez az eredmény. Látható, hogy elég a Content-type beállítása a válasz fejlécében, majd kettő soremelés után bármit kiírathatunk. 🙂

A Content-type egyébként az ún. media type (régebben MIME type) értéket tartalmazza. Részletek: https://en.wikipedia.org/wiki/Media_type.

És akkor nézzük ugyanezt perl nyelven!

#!/usr/bin/perl

use strict;
use warnings;

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

my $a = 0;
&number();

sub number {
  $a++;
  print "number \$a = $a\n";
}

A parancs kimenete hasonlatos mind parancssorban, mind a http://localhost/cgi-bin/counter.pl webcím alatt.

gvamosi@gergo1:/usr/lib/cgi-bin$ chmod +x counter.pl 
gvamosi@gergo1:/usr/lib/cgi-bin$ ./counter.pl 
Content-type: text/html

number $a = 1

Végül nézzük meg C nyelven. Megjegyzem: a C nyelvű scriptet a gcc programcsomag segítségével le kell fordítanunk. 🙂

#include <stdio.h>

int i=0;

int incrementcount()
{

  i++;
  return i;
}

int main()
{
  printf("Content-type: text/html\n\n");
  printf("The current count is: ");
  printf("%d\n", incrementcount());
  return 0;
}

És akkor nézzük meg a fordítást majd a kimenetet. Ugyanez lesz látható a http://localhost/cgi-bin/counter.cgi webcím alatt is.

gvamosi@gergo1:/usr/lib/cgi-bin$ gcc counter.c -o counter.cgi
gvamosi@gergo1:/usr/lib/cgi-bin$ ls -l
total 32
-rw-r--r-- 1 gvamosi gvamosi   216 Aug 12 03:05 counter.c
-rwxr-xr-x 1 gvamosi gvamosi 16720 Aug 12 03:05 counter.cgi
-rwxr-xr-x 1 gvamosi gvamosi   158 Aug 12 02:47 counter.pl
-rwxr-xr-x 1 gvamosi gvamosi    84 Aug 12 02:37 counter.sh
gvamosi@gergo1:/usr/lib/cgi-bin$ ./counter.cgi 
Content-type: text/html

The current count is: 1

Bámulatos, nem? 🙂 Hogy mire lesz jó ez az egész három különböző nyelvű, méghozzá benne egy natív C implementáció is? A következő fejezetekben kiderül!

Megjegyzés: natívan, bár gyorsabb a végeredmény, azért nem fejlesztünk többnyire, mert rendkívül bonyoluttá válik összetett oldalak esetén a programkód. Továbbá elég egy pici hiba, és már is “vulnerable”, azaz sérülékeny lehet a weboldalunk, amit a hacker-ek ún. exploit-tal ki tudnak használni, azaz adott esetben fel is törthetik az oldalainkon keresztül a szervereinket.