[Python] mod_python psp VS mod_php

Andrea Giammarchi andrea a 3site.it
Gio 17 Ago 2006 18:40:22 CEST


Manlio Perillo ha scritto:
> Guarda che come performance assolute Python non è meglio di PHP.
> Tempo fa qualcuno ha fatto dei semplici test.
>
> Occhio alla parola "semplici".
> In realtà un test per avere significato deve essere su una applicazione
> significativa.
vista questa risposta, mi son messo giù a fare un bench molto semplice.

il bench non fa altro che creare una stringa lunga, scriverla su un 
file, rileggerla dal file, parsarla con una regexp, splittarla o 
lavorarla per un numero preassegnato di volte.

Queste operazioni sono quasi la routine per tanti sistemi fw in php 
basati su template engines, la scrittura di tutto ad esempio è una 
peculiarità di MovableType.
Python su psp sfrutterebbe direttamente il C per parsare il file ed 
assegnare i valori come template engine, quindi mi è sembrato inutile 
paragonarli per caratteristiche, ho preferito paragonarli per similitudini.

Non ho testato un db perchè credo che i wrapper siano molto simili 
(sqlite, mysql, postgre) e la differenza la fa più il db che il 
linguaggio stesso (anche se la manipolazione gestione dei risultati 
potrebbe sicuramente dare qualche spunto in più per le conclusioni sul 
confronto)

Il test è stato fatto sullo stesso PC (centrino 1.6 con hd lento da 
5.400 rpm, 1Gb di RAM) con lo stesso Apache (2.0 che php in 2.2 ancora 
non gira o comunque ha diversi problemi)

Pagina bench.psp
<%
import time, re

# test "char by char" [python emula il tst in php ed è costretto a 
sfruttare una stringa e una lista]
def bench1(times, path):
    benchtime = getTime(None)
    b = 0
    tmp = ''
    tmpl = []
    for a in range(0, times):
        tmp = readWriteBench(path)
    b = len(tmp)
    for a in range(0, b):
        tmpl.append(tmp[a])
        tmpl[a] = ' '
    tmp = ''.join(tmpl).strip()
    return str(getTime(benchtime))

# test identico [python e php fanno esattamente le stesse cose ma python 
ha una funzione in più da gestire, la file_get_contents]
def bench2(times, path):
    benchtime = getTime(None)
    a = 0
    b = 0
    tmp = []
    while a < times:
        tmp = readWriteBench(path).split("\r\n")
        a = a + 1
    a = 0
    b = len(tmp)
    while a < b:
        tmp[a] = ' '
        a = a + 1
    tmp.append(''.join(tmp).strip())
    return str(getTime(benchtime))

# test pitoniano [python come l'avrei scritto per fare il secondo test]
def bench3(times, path):
    benchtime = getTime(None)
    tmp = []
    for a in range(0, times):
        tmp = readWriteBench(path).split("\r\n")
    for a in range(0, len(tmp)):
        tmp[a] = ' '
    tmp.append(''.join(tmp).strip())
    return str(getTime(benchtime))

# funzione analoga
def getTime(startTime):
    newtime = time.clock()
    if startTime != None:
        newtime = newtime - startTime
    return newtime

# funzione python, in core in php
def file_get_contents(fileName):
    fp = file(fileName, 'r')
    source = fp.read()
    fp.close()
    return source

# funzione analoga
def readWriteBench(path):
    writeBench(path)
    return re.sub("__([0-9]+)__\r\n", "\\1", file_get_contents(path + 
'/test.py.txt'))

# funzione analoga
def writeBench(path):
    astr = []
    for a in range(0, 10000):
        astr.append("__%i__\r\n" % a)
    fp = file(path + '/test.py.txt', 'w')
    fp.write(''.join(astr))
    fp.close()

# path del file (http://localhost/python/)
path = os.path.abspath('./htdocs/python/')

times = 20 # 50, 100 per differenza più consistente
req.write(bench1(times, path))
req.write("<hr />")
req.write(bench2(times, path))
req.write("<hr />")
req.write(bench3(times, path))
%>


Pagina bench.php
<?php

# test char by char [in php le stringhe sono virtualmente mutabili]
function bench1($times) {
    $benchtime = getTime(null);
    $str = '';
    for($a = 0; $a < $times; $a++)
        $str = readWriteBench();
    for($a = 0, $b = strlen($str); $a < $b; $a++)
        $str{$a} = ' '; # unico punto dove PHP fa la differenza
    $str = trim($str);
    return getTime($benchtime);
}

# test identico
function bench2($times) {
    $benchtime = getTime(null);
    $a = 0;
    $b = 0;
    $tmp = array();
    while($a < $times) {
        $tmp = explode("\r\n", readWriteBench());
        $a = $a + 1;
    }
    $a = 0;
    $b = count($tmp);
    while($a < $b) {
        $tmp[$a] = ' ';
        $a = $a + 1;
    }
    array_push($tmp, trim(implode('', $tmp)));
    return getTime($benchtime);
}

# test piaccaparo [come avrei scritto il secondo test per php]
function bench3($times) {
    $benchtime = getTime(null);
    $tmp = array();
    for($a = 0; $a < $times; $a++)
        $tmp = explode("\r\n", readWriteBench());
    for($a = 0, $b = count($tmp); $a < $b; $a++)
        $tmp[$a] = ' ';
    array_push($tmp, trim(implode('', $tmp)));
    return getTime($benchtime);
}

# funzione analoga
function getTime($startTime) {
    list($a, $b) = explode(' ', microtime());
    $newtime = (float)$a + (float)$b;
    if($startTime !== null)
        $newtime -= $startTime;
    return $newtime;
}

# funzione analoga
function readWriteBench() {
    writeBench();
    return preg_replace("/__([0-9]+)__\r\n/", "\\1", 
file_get_contents('test.php.txt'));
}

# funzione analoga
function writeBench() {
    $astr = array();
    for($a = 0; $a < 10000; $a++)
        array_push($astr, "__{$a}__\r\n");
    $fp = fopen('test.php.txt', 'w');
    fwrite($fp, implode('', $astr));
    fclose($fp);
}

$times = 20; # 50, 100 per differenza più consistente
echo bench1($times);
echo '<hr />';
echo bench2($times);
echo '<hr />';
echo bench3($times);
?>

Magari non sarà il migliore dei tests .. di fatto i risultati sono stati:
1 - picco di quasi 7 mega di ram rubati dal PHP durante il test contro i 
quasi 200Kb presi in prestito dal python
2 - mezzo secondo di differenza, tendente all' uno con 50 interazioni, 2 
quasi e mezzo con 100 interazioni a vantaggio di python

Probabilmente non ho configurato nemmeno benissimo mod_python perchè 
sebbene vada tutto, nel server mi ritrovo un CGI come configurazione 
(forse perchè comunque sfrutta l'installazione di python)


A voi commenti, consigli per altri bench o conclusioni :-)

Andrea Giammarchi



P.S. per quel che mi riguarda, che python risultasse più veloce anche in 
manipolazione consistente di stringhe, l'ho scoperto poco tempo fa con 
la SourceMap (http://www.phpclasses.org/browse/package/3279.html - c'è 
anche la versione Python)


Maggiori informazioni sulla lista Python