Aszinkron adatbázis lekérdezések
A PHP újabb verziói támogatnak több adatbáziskezelő interfészén (mysqli, pgsql) eleddig kevéssé használt lehetőséget: az aszinkron adatbázis lekérdezéseket. A mostani, erősen kísérletező cikkben áttekintjük ennek a funkciónak a lényegét. Vigyázat, használni csak saját felelősségre!
A PHP függvények között kutatva találtam rá az aszinkron lekérdezések (asynchronous queries) lehetőségére, amit a PHP 4.2 verziótól felfelé PostgreSQL-hez, illetve PHP 5-től MySQL esetén is használhatunk a mysqli kiterjesztésen keresztül.
Az előző megfogalmazásban a kulcsszó: a párhuzamosítás, amivel kapcsolatban fontos megemlíteni a következőket.
Ez kíváncsivá tett, ezért először megpróbáltam behatárolni, hogy valójában mekkora többletterhet ró ez a rendszerre. Ehhez a fenti rövid mintapéldát és annak szinkronizált párját futtattam néhányszor, mert párhuzamosítható feladat híján valóban a két elérés közti időkülönbség domborodik ki leginkább.
Szokványos kiépítésű asztali P4 gépen levő alap Debian sarge alatt (PHP 4.3.10 + PostgreSQL 7.4) tesztelve
Mint minden mérés eredménye, számszerű következtetéseket ebből is csak a vizsgált környezet pontos ismeretében szabad levonni, és akkor is leginkább az adott rendszerre vonatkozőan. Ebben az egyszerű stressztesztben jobban szerepelt a szinkron megvalósítás mindenesetre, a különbség nem számottevő, de nem is elhanyagolható.
A másik fontos tudnivaló, hogy PostgreSQL esetében nincs lehetőségünk nem blokkolva várakozni, illetve értesítést kapni a végrehajtás befejeződéséről. Ebben talán lesz változás, mert a libpq, PHP PostreSQL illesztést végző C könyvtár erre lehetőséget biztosít.
PostreSQL használata esetén továbbá lehetőségünk van egyszerre - egy pg_send_query() hívással - több SQL parancsot is elküldeni, majd mindegyik eredményéről külön-külön tájékozódni, de csakis a lekérdezések sorrendjében. Az egy kapcsolaton át küldött lekérdezések egymáshoz képest az adott sorrendben futnak le. Ha több lekérdezést egymástól feltartása nélkül akarunk indítani, akkor azoknak külön adatbázis-kapcsolatokat kell biztosítani (pg_connect()).
Második legvalószínűbb felhasználási módja a végeredmény tényleges ellenőrzése nélküli SQL parancsok esete, ilyenek lehetnek például: a nem létfontosságú naplóüzenetek rögzítése, és egyéb adatmanipulációs utasítások (UPDATE, DELETE, INSERT) futtatására. Ezzel nem akarok senkit sem arra bátorítani, hogy a kiadott SQL parancsok végkifejletét elfelejtse ellenőrizni! Azon ritka esetekben, amikor ez megtehető, lehet élni ezzel a lehetőséggel.
További potenciális felhasználási terület lehet a rétegekbe szervezett alkalmazások területe. Az alkalmazási rétegben létrehozunk egy objektumot, amiben elindítjuk a lekérdezést. A tényleges adatlekérést azonban a megjelenítésért felelős sablonmotor végezteti el majd a sablon kitöltésekor. Ennek a megoldásnak a gyenge pontja a hibakezelés korlátozottsága illetve, hogy az alkalmazási rétegek közötti határ elmosódik. (Mentségemre legyen mondva, hogy léteznek olyan keretrendszerek, ahol a kód elsősorban nem a rétegezés szerint van felosztva, hanem az adatobjektumok köré szervezve, ahol valami hasonló történik, mint itt.) Az alábbi példa csak az elgondolást szemlélteti, mivel nincs mit párhuzamosítani benne!Ez a még hasznosabb lehet, ha az adatbázis-kiszolgáló és a PHP külön hálózati gépen található, és közöttük a hálózati terheltség miatt lassú a kapcsolat, ami érzékelhetően csökkenti a hagyományos, szinkron adateléréssel működő szkriptek sebességét.
Amint a cikk bevezetőjében írtam, ezzel a cikkel elsősorban ezen új lehetőség bemutatása volt a célom, némi támpontot adva a lehetséges felhasználási területek számbavételével. Mivel sok információ jelenleg nem áll rendelkezésre, aki erre adja a fejét, az sok kísérletezésre számítson! De ha soha nem kísérleteznénk, még mindig a "hello world!"-nél tartanánk! Szerencse fel!
■ Előkép
A mai webalkalmazások legtöbbje elképzelhetetlen adatbázisháttér nélkül, amelyekre a rengeteg információ rendszerezett tárolása és ellenőrzött módosítása miatt van szükség. Ezek az igények azonban olyan robosztus rendszereket, adatbázis kiszolgálókat "szülnek", amelyeknek a teljesítményét legtöbbször egyedi módon kell fokozni. A legszűkebb keresztmetszet általában az idő szokott lenni, és így az adatbázisok gyorsítására igen sok megoldás született. Ezeket általában kettő illetve három nagy csoportba sorolhatjuk.- A "rendszer szintű" erőforrás-hangolások nem érintik az általunk írt kódot, hanem az azt futtató rendszer komponensei között osztja el az erőforrásokat optimálisan, mint pl.: nagyobb osztott memóriahasználat, adatbázis fizikailag külön háttértárolón, stb.
- Az adatbázis lekérdezések optimalizációja a kódunkon belül, amelynek alapvetően két fő csapásiránya mutatkozik: maguknak az SQL utasítások optimalizációja, illetve az interfészhívások észszerűsítése - módosítása. Az első esetben több lekérdezés egybeolvasztásáról lehet szó, vagy azonos eredményt adó alternatívák közül a leggyorsabb kiválasztásáról. A másik esetben azonban magát az SQL kéréseket változatlan formában hagyva magát a programunkat struktúráljuk át olyan módon, hogy az gyorsabban fusson.
A PHP függvények között kutatva találtam rá az aszinkron lekérdezések (asynchronous queries) lehetőségére, amit a PHP 4.2 verziótól felfelé PostgreSQL-hez, illetve PHP 5-től MySQL esetén is használhatunk a mysqli kiterjesztésen keresztül.
Az aszinkron működés
Miről is van szó, és hol lép fel az aszinkronitás? A hagyományos*_query()
függvények "megvárják" a kiadott SQL utasítás végeredményét, ezzel szemben az aszinkron *_send_query()
csak a parancs elküldésének idejéig "tartóztatja fel" a hívást kezdeményező szkript futását. A vastag nyilak jelzik a blokkoló függvényhívásokat, míg a vékonyabbak a vezérlés megosztástást és átadását.
Miért jó ez? - elmélet
Az elmélet egyszerű. Az aszinkron működésből kifolyólag párhuzamosítani lehet az adatbázis-műveleteket más PHP-ból indított feladatok végrehajtásával. Az SQL parancs kiadása után a PHP újabb utasításokat végezhet el, majd elég az eredményt akkor lekérni, amikor már annak feldolgozása nem halasztható tovább. Ez utóbbi tipikusan az adatok megjelenítését jelenti a kiküldendő HTML-ben, de látunk példát másféle alkalmazásukra is.Asztali alkalmazások körében már régóta elterjedt gyakorlat, hogy a felhasználói interaktivitás zavartalansága érdekében a hosszabb, nem megszakítható műveleteket külön programszálak végzik el a háttérben, így nem tűnik úgy, mintha a program nem válaszolna a felhasználó üzeneteire. PHP-ban nincs lehetőség bizonyos műveletek külön szálakon indítani, ennek ellenére itt is valami hasonlóról van szó.
Az előző megfogalmazásban a kulcsszó: a párhuzamosítás, amivel kapcsolatban fontos megemlíteni a következőket.
- Az egész "hadművelet" nem ér semmit, ha nincs mit párhuzamosítani, sőt akár káros is lehet! Ha nincs olyan műveletsor, amit párhuzamosan végre tudna hajtani a PHP, amíg az adatbázis-kiszolgáló végez, akkor végeredményben a szkript így is - úgy is várakozni kényszerül.
- Nem mellékes, hogy milyen feladatokat és hogyan "párhuzamosítunk". Ez alatt azt értem, hogy ha pl. több egymástól független SQL utasítást "szedünk csokorba", akkor érdemes előzetes felmérést végezni, hogy melyik kérés teljesítése mennyi ideig tart, és eszerint elrendezni azok indítását a programon belül.
- A folyamatok párhuzamosításával nyert időnek arányban kell lennie az általa okozott többletterheléssel. Az aszinkron lekérdezések bevezetése a PHP források nem kis átalakításával jár, ami rögtön nem elhanyagolható plusz munkaórákat jelent. Emellett az is előfordulhat, hogy többet vesztünk a réven, mint amennyit nyerünk a vámon. Az átalakítás megváltoztatja a program futási paramétereit, mert több függvényhívást jelent már PHP szinten is, ami több interakciót jelent a felszín alatt.(Lásd a fenti ábrát!)
Megvalósítás
Elsőre nem különösebben bonyolult és nem sokban tér el az aszinkron lekérdezés programozása a hagyományostól:<?php
$conn = pg_connect("dbname=asynctest") or die("nincs kapcsolat!");
// a frissen létrehozott kapcsolatnak használhatónak kell lennie!
assert ('!pg_connection_busy($conn)');
// SQL parancs küldése aszinkron végrehajtásra
pg_send_query($conn, "select * from test;") or die("keres nem sikerult!");
// ... egyéb teendők párhuzamos elvégzése ...
// várakozás az eredmény "elkészültére" + feldolgozás
for ( $res = pg_get_result($conn); $row = pg_fetch_object($res); )
{
echo $row->id, " ", $row->name, "\n";
}
?>
- A szokásos pg_query() (illetve mysqli_query()) függvények helyett pg_send_query()-t kell használni. A továbbiakban csak a PostgreSQL-hez tartozó függvényeket említem, mivel azok a most még jobban elterjedt PHP 4 szériában is jelen vannak, valamint további funkciókat is biztosítanak a MySQLi-hez képest.
- A parancs elküldése előtt meg kell bizonyosodni arról, hogy felhasznált adatbázis-kapcsolat (
$conn
) szabad, más lekérdezés nem fut rajta, csak ezután lehet elküldeni a végrehajtani kívánt parancsot.
- Mivel a
pg_send_query()
visszatérésével még nem áll rendelkezésre az eredmény, ezért a szükséges azonosítót egy új függvényhívással kell megszerezni, erre való a pg_get_result(). Jó tudni azonban, hogy e hívássalblokkolja
a szkript futását és addig nem tér vissza, amíg a lekérdezés eredménye rendelkezésre nem áll.
Tényleg jó ez? - a gyakorlat
Szép dolog az elmélet, de mindez jelent-e valami előnyt a gyakorlatban. Meglepve tapasztaltam, hogy igen kevés információt találni erről a technikákról az Interneten, a PHP-s a megoldásokról pedig szinte semmit. (Ezúton is kérek mindenkit, aki tud ilyen leírásokról, megjegyzésként biggyessze a cikk után!) Ez a megdöbbentő információhiány már kezdett gyanússá válni.Ez kíváncsivá tett, ezért először megpróbáltam behatárolni, hogy valójában mekkora többletterhet ró ez a rendszerre. Ehhez a fenti rövid mintapéldát és annak szinkronizált párját futtattam néhányszor, mert párhuzamosítható feladat híján valóban a két elérés közti időkülönbség domborodik ki leginkább.
# ab2 -t 60 -n100 -c20
Document Path: /sync.php
Complete requests: 262
Requests per second: 4.37 [#/sec] (mean)
Time per request: 4581.022 [ms] (mean)
Time per request: 229.051 [ms] (mean, across all concurrent requests)
Document Path: /async.php
Complete requests: 255
Requests per second: 4.25 [#/sec] (mean)
Time per request: 4706.624 [ms] (mean)
Time per request: 235.331 [ms] (mean, across all concurrent requests)
Document Path: /sync.php
Complete requests: 262
Requests per second: 4.37 [#/sec] (mean)
Time per request: 4581.022 [ms] (mean)
Time per request: 229.051 [ms] (mean, across all concurrent requests)
Document Path: /async.php
Complete requests: 255
Requests per second: 4.25 [#/sec] (mean)
Time per request: 4706.624 [ms] (mean)
Time per request: 235.331 [ms] (mean, across all concurrent requests)
Szokványos kiépítésű asztali P4 gépen levő alap Debian sarge alatt (PHP 4.3.10 + PostgreSQL 7.4) tesztelve
Mint minden mérés eredménye, számszerű következtetéseket ebből is csak a vizsgált környezet pontos ismeretében szabad levonni, és akkor is leginkább az adott rendszerre vonatkozőan. Ebben az egyszerű stressztesztben jobban szerepelt a szinkron megvalósítás mindenesetre, a különbség nem számottevő, de nem is elhanyagolható.
A másik fontos tudnivaló, hogy PostgreSQL esetében nincs lehetőségünk nem blokkolva várakozni, illetve értesítést kapni a végrehajtás befejeződéséről. Ebben talán lesz változás, mert a libpq, PHP PostreSQL illesztést végző C könyvtár erre lehetőséget biztosít.
PostreSQL használata esetén továbbá lehetőségünk van egyszerre - egy pg_send_query() hívással - több SQL parancsot is elküldeni, majd mindegyik eredményéről külön-külön tájékozódni, de csakis a lekérdezések sorrendjében. Az egy kapcsolaton át küldött lekérdezések egymáshoz képest az adott sorrendben futnak le. Ha több lekérdezést egymástól feltartása nélkül akarunk indítani, akkor azoknak külön adatbázis-kapcsolatokat kell biztosítani (pg_connect()).
Felhasználási tippek
Az elkedvetlenítő kezdés után néhány alkalmazási területen mégis hasznosnak vélem ezt a technikát, ha nem is azonnal, de a közel jövőben. Az első és talán legkézenfekvőbb lassú, nagy bonyolultságú lekérdezések esetén használni. Azt is figyelembe kell venni, hogy az adatbázisnak átadott parancs milyen további parancsok futását indítja be (szabályok, triggerek), amik megnövelik az eredeti lekérdezés teljes futási idejét.Második legvalószínűbb felhasználási módja a végeredmény tényleges ellenőrzése nélküli SQL parancsok esete, ilyenek lehetnek például: a nem létfontosságú naplóüzenetek rögzítése, és egyéb adatmanipulációs utasítások (UPDATE, DELETE, INSERT) futtatására. Ezzel nem akarok senkit sem arra bátorítani, hogy a kiadott SQL parancsok végkifejletét elfelejtse ellenőrizni! Azon ritka esetekben, amikor ez megtehető, lehet élni ezzel a lehetőséggel.
További potenciális felhasználási terület lehet a rétegekbe szervezett alkalmazások területe. Az alkalmazási rétegben létrehozunk egy objektumot, amiben elindítjuk a lekérdezést. A tényleges adatlekérést azonban a megjelenítésért felelős sablonmotor végezteti el majd a sablon kitöltésekor. Ennek a megoldásnak a gyenge pontja a hibakezelés korlátozottsága illetve, hogy az alkalmazási rétegek közötti határ elmosódik. (Mentségemre legyen mondva, hogy léteznek olyan keretrendszerek, ahol a kód elsősorban nem a rétegezés szerint van felosztva, hanem az adatobjektumok köré szervezve, ahol valami hasonló történik, mint itt.) Az alábbi példa csak az elgondolást szemlélteti, mivel nincs mit párhuzamosítani benne!
<?php
class person {
var $conn = NULL;
var $res = NULL;
var $row = NULL;
function person ($conn, $id) {
$this->conn = $conn;
return pg_send_query($conn, "SELECT * FROM person WHERE id=$id;");
}
function __get ($property) {
if ( !isset($this->res) ) {
$this->res = pg_get_result($this->conn);
$this->row = pg_fetch_array($this->res);
}
return $this->row[$property];
}
}
$conn = pg_connect("dbname=bigdeal");
$tpl =& new template();
$tpl->register('person', new person($conn, $_GET['id']));
// ... egyéb műveletek párhuzamosan
$tpl->display('person.tpl');
?>
<html>
<title>person.tpl - a rossz példa sablonja</title>
<ul>
<li>Név: {$person->name}
<li>Cím: {$person->address}
</ul>
</html>
Amint a cikk bevezetőjében írtam, ezzel a cikkel elsősorban ezen új lehetőség bemutatása volt a célom, némi támpontot adva a lehetséges felhasználási területek számbavételével. Mivel sok információ jelenleg nem áll rendelkezésre, aki erre adja a fejét, az sok kísérletezésre számítson! De ha soha nem kísérleteznénk, még mindig a "hello world!"-nél tartanánk! Szerencse fel!
tök jó
Említetted, hogy a technika egyik felhasználási módja az, hogy a nem lényeges parancsok ellenőrzése mellőzhető... Lehet hogy félreértettem, de én úgy gondolom, hogy a stabilítást nem áldozhatjuk fel a gyorsaság oltárán, márpedig a hibakezelés mellőzése egy ilyen dolog...
Azért elég sok veszélyt rejt magában ez a párhuzamosítás, nem? Arra gondolok, hogy ha pl. egy php kód nem elég intelligens és mondjuk táblába is illeszt, meg le is kérdez ugyanabból... Azért azt célszerű lineárisan végezni. ;)
Ez csak piszkálódáképpen, fel ne vedd: írtad valahol hogy a különbség nem számottevő, de nem is elhanyagolható. Akkor milyen? :))
[ dtamas ]
reflekt
Az említettt részben -- de a cikk egészében -- alatt az SQL lekérdezést/utasítást értettem. Remélem, sehol nem használtam PHP utasításokra vagy kódokra érthetően. Amikor tehát ezt írtam, akkor tulajdonképpen arra gondoltam, hogy nem vizsgáljuk meg az SQL resultset-et, hanem bízunk valamiben. Természetesen egyet értek veled, szerintem sincs értelme és helye az SQL parancsok szabadjára engedésének egy robosztus alkalmazásban - általában. (Sajnos, azonban már sok mindent láttam.)
Most egyetlen lehetséges és valamennyire észszerű felhasználási módja jut ennek eszembe: PHP munkamenet-kezelő szemétgyűjtő algoritmusa (
DELETE FROM session ...
). Itt talán nem olyan vészes, ha ezt megengedjük.Ha a sablonos példa kapcsán említett korlátolt hibakezelésre gondolsz, az viszont teljességgel megoldható, csak ízlés kérdése, ki hogyan teszi. Ezért és mivel nem ez volt a téma, ezzel nem foglalkoztam.
Párhuzamosítani bármit lehet, amiknek a bemenetei egymástól függetlenek, és lehetőleg nem azonos erőforráson kell osztozniuk (lásd
$conn
- kapcsolatazonosító). Van pontosabb definíció is, de ez kb. megfelel. Ez azt is jelenti, hogy míg az adatbázisba írunk vagy onnan kérdezük bármilyen egyéb tevékenységgel - legyen az levélküldés, kép- vagy grafikonrajzolás, feltöltött fájlok$_FILE[]
feldolgozása, backup mentés SQLite-ba, RPC hívások - elüthetjük az időt. Ugyanazt a táblát is lehet bogarászni, mivel a valódi adatbázis kiszolgálók fel vannak készítve a konkurrens elérésre. (A PostgreSQL ebben is nagy.) Az viszont már rajtad áll, h. mit kezdesz az eredménnyel!A különbség pedig figyelembe veendő ;) Viccet félretéve az utolsóra nincs mentségem, és tervezem, hogy a hétvégén mellékelek a cikkhez még több mérési adatot. (A késés oka, h. nem minden esetben volt egyértelmű az eredmény, és ez elbizonytalanított. Inkább tesztelem még, minthogy még nagyobb hülyeségeket írjak ;) Tehát várható a jövő hét folyamán itt egy hosszú, példaprogramokkal és mérési adatokkal teli megjegyzés.
TCP - UDP analógia
A fenti dolog is arról szól, hogy a TCP használata esetén biztosított, hogy a csomagok a megfelelő sorrendben, hibátlanul eljussanak a címzetthez. Vszont vannak olyan alkalmazások, ahol megengedhető, hogy néhány csomag elvesszen, cserébe nagyobb az átviteli sebesség. Ennek mintájára elképzelhetőnek tartom, hogy van létjogosultsága ennek a módszernek.
Ráadásul ha jobban megnézed itt nem erről van szó. Csak időben szétválasztódnak a dolgok. Ugyanúgy van lehetőséged ellenőrizni, csak közben egy csomó egyéb hasznos dolgot megtehetsz.
Érdekes lehet még a téma kapcsán mysql esetén a mysql_unbuffered_query() parancs.
Felhő
Marha jó
Ha az oldalon a grid előtt kisebb adatokat akarok még kirakni, akkor pont jó, hogy a nagy lekérdezést a teljes oldal összeállítása után kell csak kiolvasni.
Köszönjük néked
Na, erre nem is számítottam
Jó lenne, ha egy valós alkalmazás kapcsán a tapasztalataidról be tudnál majd számolni! Hozott-e valami javulást vagy sem?
db párhuzamos
másról van szó
A programok azonban sokszor várakozni kényszerülnek valamilyen lassabb periférián (merevlemez, hálózati csatoló, stb.) keresztül érkező adatra. Ilyenkor az operációs rendszer "feladatot vált" (taszkot vált), és egy másik program utasításait futtatja a CPU-n, és így cserélgeti őket állandóan. (Bocs a pongyolaságért, de remélem, érthető volt a lényeg.) Ez azt jelenti, h. egy processzoros gépen is van létjogosultsága ezeknek a módszereknek.
A lekérdezések végrehajtási sorrendje főként a DBMS-től függ. Mivel ezeket a szoftvereket is nagyszámú konkurrens -- egyidőben fellépő -- művelet elvégzésére tervezték, nem fognak egy egyszerű gyors lekérdezést "hátrébbb sorolni", csak mert később futott be. Az operációs rendszer lehetőségeit kihasználva, a lekérdezéseket elkezdik egymástól függetlenül végrehajtani, és amelyik "végrehajtó programja" hamarabb végez, az lesz kész előbb. szerintem ;)
Gondolkodván a válasz vála
Egyébként a dbms belső párhuzamosításáról csak annyit, hogy minden rendszer megérzi egy nagy lekérdezés futását a szerveren. Szinte látod, hogy eddig szaladt minden aztán Ágika elindította az este 6 után futtatható lekérdezést napközben és megállt a pénztár :-)
nem jól látod
Amit te feszegetsz az a valódi párhuzamoság és az ilyen ki sgépeken megvalósított "konkurrencia" közti különbség. (Bár párhuzamosításnak általában egy processz egymástól független, azaz párhuzamosítható utasításait szokták nevezni, és ennek valóban fontos feltétele, h. több CPU álljon rendelkezésre, amin ezek a részek egymás mellett tudnak futni.)
A mérési eredményeket majd közlöm később. A cikk megjelenésekor azért nem kerültek be, mert a
pg_conncetion_busy()
fv-re épültek, de ennek a teljesítménye csalódást jelentett, és szerintem nem a valós képet mutatja. Az azonban kizárt, hogy ez csak a hardware kiépítettségtől függjön.Nem a lekérdezések párhuzamosak
Itt most nem igazán a lekérdezések párhuzamosításáról van szó. A lényeg, hogy amíg az adatbázis a lekérdzés eredményének összeállításán dolgozik, addig te egyéb dolgokat is tehetsz. A kettő együttes futtatása adott esetben jobb erőforrás kihasználtságot eredményezhet.
Felhő
Teszteredmények
-n100
paraméterrel, ebben az esetben mellőztem a kokurrens terhelésvizsgálatot.Az első összehasonlításban kizárólag a
$res
lekérdezés azonosító megszerzése volt a cél. A lehető legyszerűbb lekérdezéstSELECT * FROM test
futtatva jelentős eltérés nem tapasztalható:Requests per second: 5.05 [#/sec] (mean)
Requests per second: 5.65 [#/sec] (mean)
# async.php
Requests per second: 5.01 [#/sec] (mean)
Requests per second: 5.68 [#/sec] (mean)
Ez ellentétben áll a cikkben korábban írt véleményemmel. Ezt az eltérést a tesztprogram első verziójában használt
pg_connection_busy()
függvény okozta. Ezzel lehet ellenőrizni, hogy a használni kívánt adatbázis-kapcsolat foglalt-e. A tesztprogram ugyanazon a kapcsolaton keresztül bonyolított le több SQL parancsot, és egy várakozó ciklus biztosította, hogy az előző SQL már véget ért:INSERT
utasításokkal teszteltem az aszinkron elérést. (Hiba volt.)A következő példa tipikus feladatot szimulál, először az adott feltételnek megfelelő rekordok számát kérdezzük le, aztán ugyanazon rekordok némelyikét:
Requests per second: 6.54 [#/sec] (mean)
Time per request: 152.866 [ms] (mean)
# async.php - usleep(1) ciklusmaggal
Requests per second: 13.28 [#/sec] (mean)
Time per request: 75.328 [ms] (mean)
# async.php - csak pg_get_result() a várakozó ciklus helyett
Requests per second: 16.26 [#/sec] (mean)
Time per request: 61.498 [ms] (mean)
# sync.php
Requests per second: 15.98 [#/sec] (mean)
Time per request: 62.594 [ms] (mean)
Ebből látható, hogy a
pg_connection_busy()
-t csakusleep()
függvénnyel együtt érdemes használni várakozó ciklusban, mert így a PHP-t futtató processz nem köt le felesleges erőforrásokat. Némi eltérés mutatkozik a várakozó ciklus nélküli, csakpg_get_result()
-ot tartalmazó megoldáshoz képest.Ebből arról következtetek, hogy a
pg_connection_busy()
-t akkor érdemes használni, ha van olyan feladat, amit a kapcsolat állapotától függően még az eredmények lekérdezése előtt érdemes megtenni, de az sem baj, ha ez csak az eredmények megérkezése után történik. Várakozásra megfelel a cikkben említettpg_get_result()
, ami azonban blokkolja a PHP futását. (A várakozó ciklus ugyanezt teszi persze.) Ez az aszinkron használat és a szinkron időeredményei közel azonosak voltak több futtatás után, hol az egyik hol a másik bizonyult gyorsabbnak.Ha két külön adatbáziskapcsolaton keresztül kértem le a két lekérdezés eredményét, akkor nagy(obb :) átlagban jobban megközelítette az aszinkron a szinkron elérés teljesítményét
pg_connection_busy()
használatával: