UPDATE!
Biorąc sobie do serca uwagę o pominięciu PDO w teście postanowiłem sprawdzić tą bibliotekę w szczególności że jest ona integralną częścią PHP.
Przy okazji sprawdziłem jeszcze jak mają się PEAR i PDO gdy zastosujemy tranzakcję.
Nie bawiłem się już rysunki, więc wyniki w postaci liczbowej.
PDO SELECT 500tys rekordów: 3.25s
PDO INSERT 500tys rekordów bez transakcji: 2.86m
PDO INSERT 500tys rekordów z tranzakcjami: 25.8s
PEAR INSERT 500tys rekordów z tranzakcjami: po 15m odchciało mi się czekać :>
Jak widać uwaga jaką poczynił Dawidgarus była zupełnie słuszna. PDO jest najlepszy pod każdym wzgęldem.
//============================================================================
Witam.
Ostatnio nie było u mnie w pracy kierownika i mogłem zająć się duperelami, więc postanowiłem porównać wydajność PHP względem Python'a w aplikacjach WWW.
W internecie znalazłem opinie jakoby serwisy napisane w oparciu o mod_python były dwukrotnie szybsze niż te napisane w mod_php, ale nie natrafiłem na żadne faktyczne porównanie szybkości wykonywania skryptów.
Opracowałem więc swój własny test sprawdzający to co mnie interesuje najbardziej czyli szybkość pracy z bazą danych.
Test składał się z dwóch części.
Pierwszy polegał na wprowadzeniu 500tys. rekordów do pustej tabeli w bazie danych MySQL.
Drugi na pobraniu wszystkich wprowadzonych wpisów i małego zmodyfikowaniu każdego w kodzie (nie bazie).
Tworząc skrypty do testów postarałem się aby były one jak najbardziej do siebie podobne. Stworzyłem szablon HTML który przy pomocy mechanizmów AJAX wywoływał zadany skrypt i wyświetlał jego wynik. Pomiaru czasu mogłem dzięki temu dokonać za pomocą plugin'u Firebug.
Platforma testowa:
Intel C2D 2.66 GHz
1 GB RAM
Ubuntu 2.6.27-11-generic
apache2 2.2.9-7ubuntu3
mysql 5.0.67-0ubuntu6
libapache2-mod-php5 5.2.6-2ubuntu4.1
libapache2-mod-python 3.3.1-3
python 2.5.2-1ubuntu1
php 5.2.6-2ubuntu4.1 (takie samo php-cli)
firefox 3.0.6-0ubuntu0.8.10.1
Baza:
Kod: Zaznacz cały
CREATE TABLE `zzz_aa_pracownicy` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`imie` varchar(255) collate utf8_polish_ci NOT NULL,
`nazwisko` varchar(255) collate utf8_polish_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci ROW_FORMAT=COMPACT;
Kod: Zaznacz cały
<html>
<head>
<script type="text/javascript">
function getName() {
var c = document.getElementById('cont');
var xmlHttp;
try { xmlHttp=new XMLHttpRequest(); } catch(e) { xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); }
xmlHttp.open("GET","tu_sciezka_do_skryptu",true);
xmlHttp.onreadystatechange=function() {
if(xmlHttp.readyState==4) {
c.innerHTML = xmlHttp.responseText;
}
}
xmlHttp.send(null);
}
</script>
</head>
<body>
<button onClick="getName()">Dawaj</button>
<div id="cont"></div>
</body>
</html>
//=======================================================
TEST 1: Wprowadzenie do bazy 500 000 rekordów.
PYTHON:
Kod: Zaznacz cały
import MySQLdb;
def index():
db = MySQLdb.connect(host="localhost", user="user", passwd="passss", db="db");
cursor = db.cursor();
for i in range(0, 500000):
q = "INSERT INTO zzz_aa_pracownicy(imie, nazwisko) VALUES('imie %d', 'nazwisko %d')" % (i, i);
cursor.execute(q);
db.commit();
return "OK";
Kod: Zaznacz cały
<?php
$db = mysql_connect("localhost", "user", "passss");
mysql_select_db("db", $db);
for($i = 0; $i < 500000; $i++)
mysql_query("INSERT INTO zzz_aa_pracownicy(imie, nazwisko) VALUES('imie $i', 'nazwisko $i')", $db);
mysql_close($db);
echo "OK";
?>
Kod: Zaznacz cały
<?php
$DSN = "mysql://user:passs@localhost/db";
require_once("PEAR/MDB2.php");
$db = MDB2::connect($DSN);
for($i = 0; $i < 50000; $i++)
$db->query("INSERT INTO zzz_aa_pracownicy(imie, nazwisko) VALUES('imie $i', 'nazwisko $i')");
$db->disconnect();
echo "OK";
?>
Każdy skrypt został wykonany 10 a wynik końcowy jest średnią. Po każdym wprowadzeniu danych, były one sprawdzane pod względem poprawności, a następnie kasowane, tak aby za każdym razem skrypt wypełniał pusta tabelę.
Proszę zwrócić uwagę, że PHP_PEAR dodaje tylko 50 000 rekordów. Jest to spowodowane tym, że przy 500 000 po 20min czekania na zakończenie skryptu poddałem się. Nie pomogło powiększanie pamięci ani inne zabiegi.
PYTHON: 50.15s
PHP: 178.20s
PHP_PEAR: 304.20s

//=======================================================
TEST 2: Wczytanie 500 000 rekordów z bazy.
PYTHON:
Kod: Zaznacz cały
import MySQLdb;
def index():
db = MySQLdb.connect(host="localhost", user="user", passwd="passs", db="db");
cursor = db.cursor(MySQLdb.cursors.DictCursor);
cursor.execute("SELECT * FROM zzz_aa_pracownicy");
pr = [];
i = 1;
for i in range(cursor.rowcount):
r = cursor.fetchone();
r['imie'] = "%d" % i;
r['nazwisko'] = "%d" % i;
pr.append(r);
i += 1;
ret = "%d" % cursor.rowcount;
return ret;
PHP:
Kod: Zaznacz cały
<?php
ini_set("memory_limit","300M");
$db = mysql_connect("localhost", "user", "passs");
mysql_select_db("db", $db);
$res = mysql_query("SELECT * FROM zzz_aa_pracownicy", $db);
$num = mysql_num_rows($res);
$pr = array();
for($i = 0; $i < $num; $i++)
{
$r = mysql_fetch_assoc($res);
$r["imie"] = $i;
$r["nazwisko"] = $i;
$pr[] = $r;
}
mysql_close($db);
echo $num;
?>
Kod: Zaznacz cały
<?php
ini_set("memory_limit","300M");
$DSN = "mysql://user:passs@localhost/db";
require_once("PEAR/MDB2.php");
$db = MDB2::connect($DSN);
$res = $db->query("SELECT * FROM zzz_aa_pracownicy");
$num = $res->numRows($res);
$pr = array();
for($i = 0; $i < $num; $i++)
{
$r = $res->fetchRow(MDB2_FETCHMODE_ASSOC);
$r["imie"] = $i;
$r["nazwisko"] = $i;
$pr[] = $r;
}
$db->disconnect();
echo $num;
?>
Procedura testowa taka sama.
W przypadku PHP musiałem jawnie zadeklarować ilość przydzielanej pamięci. 300M to troszkę ponad 40MB nadwyżki. Przy 250M program wciąż krzyczał o więcej.
Ponieważ skrypty miały być jak najbardziej podobne nie wykorzystałem w pythonie, oraz PEAR funkcji fetchall(). Przetestowałem jednak jeszcze wersję z tą funkcją i wyniki były na tyle zbliżone że pominąłem ją w teście.
PYTHON: 5.83s
PHP: 3.76s
PHP_PEAR: 10.04s

//=======================================================
Jako ciekawostkę uruchomiłem także skrypty w konsoli aby sprawdzić jak ma się wydajność modułów apacha do wersji konsolowych. Co ciekawe różnice nie były wielkie.
TEST 1 CON:
PYTHON:
matis@matis-desktop:~/public_html/python$ time python insert.py
real 0m50.567s
user 0m19.913s
sys 0m3.076s
PHP:
matis@matis-desktop:~/public_html/python$ time php insert.php
real 2m35.533s
user 0m3.248s
sys 0m3.072s
Mam nadzieję, że porównanie owo się komuś przyda przy wyborze języka skryptowego do jego zastosowań.
Zapraszam do dyskusji. :)
Natomiast adminów i moderatorów proszę o wyrozumiałość co do długości posta :)