PHP osztályok lassúak
Sziasztok,
elkezdtem írni egy keretrendszert php-ben, és OO alapúra akarom csinálni.
Létrehoztam pár teljesen tipikus osztályt (page, input, form osztályok).
Ha csak beinclude-olom azt a 8 osztályt, ami eddig megvan, a betöltési
idő 0.0005-ről 0.0026-ra ugrik meg. Ha példányosítom is őket, akkor 0.0034-re.
A későbbiekben tervezem majd az __autoloader használatát, és láttam tippeket
valami EAccelerator nevű szoftver alkalmazására is, de a kérdésem az, hogy
normális-e hogy csak az osztályok betöltése ilyen mértékben megnöveli az
oldal betöltését?
Lehet ez ellen tenni valamit, gyorsítani?
Üdv,
dj
■ elkezdtem írni egy keretrendszert php-ben, és OO alapúra akarom csinálni.
Létrehoztam pár teljesen tipikus osztályt (page, input, form osztályok).
Ha csak beinclude-olom azt a 8 osztályt, ami eddig megvan, a betöltési
idő 0.0005-ről 0.0026-ra ugrik meg. Ha példányosítom is őket, akkor 0.0034-re.
A későbbiekben tervezem majd az __autoloader használatát, és láttam tippeket
valami EAccelerator nevű szoftver alkalmazására is, de a kérdésem az, hogy
normális-e hogy csak az osztályok betöltése ilyen mértékben megnöveli az
oldal betöltését?
Lehet ez ellen tenni valamit, gyorsítani?
Üdv,
dj
Durva...
Gyorstárazás
kipróbáltam
Viszont: lemértem az időigényeket a betöltetlen/betöltött/példányosított osztályokkal, és sajnos azt tapasztaltam, hogy mindkét szerver esetében hasonlóan arányulnak a számok.
Tehát lehet, hogy a gép gyenge, de az osztályok betöltése bizony itt is és ott is ugyanannyi erőforrásba kerül.
Osztályok?
nem rossz
Az eredmény alapján kezd közelíteni a valósághoz: kb. ugyanannyi idő volt, mint az osztályok betöltése. Ugyanakkor megdöbbent, hogy a 2 xeon processzorral futó gépen hogyan tarthat 0.0034 másodpercig 8 osztály betöltése. A rendszer nem mondható terheltnek, a load alig megy 0.3 fölé.
Ezzel a tendenciával 30-50 osztály betöltése akár 0.02 másodpercig is eltarthat, és akkor még nem is csináltam semmit. Egy ilyen "üres" oldalból másodpercenként 50-et tudok legenerálni, ami egyáltalán nem mondható soknak, itt lenne a php-nek a határa?
Mivel tudok még gyorsítani? FastCGI? Lightthpd?
Valami nem stimmel...
profiler
javaslat?
van :)
törlendő
csúnyán is néznénk ki...
Csak jelzem, hogy célszerű csak azt behúzni, ami kell és nem többet.
A másik hiba a túlságosan szétcincált fájlokkal szokott lenni. Ha nem használsz fájl-gyorsítást (APC vagy eAccelerator), akkor ha 50 fájl húzol be az qrrva sokáig fog tartani. Persze mindezt képzeld el milliszekundumokban.
Amúgy mivel lenne 30-50 fájl? Csak érdekelne, hogy miket szeretnél külön pakolni?
Szétcincálás...
10 include vs 10x méret?
A kérdés tulajdonképp megfogalmazható úgy is, hogy proc.idő, vagy memóriafoglalás, ugye?
inkább 10x méret
pontosítás :)
Ha nincs, akkor azzal jársz jobban, ha több fájlba bontos szét a dolgaid, és mindig akkor töltesz be valamit, amikor szükség van rá. Ez logikus is, hiszen az értelmezőnek ilyenkor a kódot le kell fordítania byte kódra, tehát minél kevesebb a kód, annál gyosrabb.
Ha van opcode cache, akkor ez nem számít, hisz csak egyszer történik meg. Ez esetben az a jobb, ha egy fájlban húzod be a dolgokat, mert a behúzással kapcsolatos járulékos költség csak egyszer szerepel.
Nem olyan régi verzióban teszteltem ezt. Éles rendszerben használt főbb include-okat másoltam össze, kb. 10 db. file. Opcode cahce nélkül a külön fájl esetében ha csak pár fájlt húztam be, akkor jóval gyorsabb volt, mint az egy nagy fájl. Olyan 7-8 fájl környékén (ez kb. a kódok 80%-a volt) lett egálban a kettő. Opcode cache esetében már 3 fájl behúzása is lassabb volt, mint az egy nagy. Ráadásul a különbség attól is függött, hogy mennyire terhelt a gép IO-ban. Kitettem éles szerverre (durván terhelt), és ha behúztam külön az összes fájlt, meg az egy nagyot, akkor az előbbi 8-szor lassabb volt.
Üdv,
Felhő
Köszönöm!
oké, pontatlan voltam
félreért.
Jelenleg 3 fájlból töltődnek be az osztályok, amiknek együttes helyigénye nincs 5k sem.
Amúgy miért lenne furcsa 30-50 osztállyal dolgozni egy komplex weblap esetében?
sajátomban...
Azt írtad: 30-50 osztály betöltése.
Egy komplex weblap esetében lehet több is, kevesebb is nincs mindenre kenőcs. De én alapból soknak tartom egy általános portálhoz.
Betölteni IMHO csak azt kell, ami kell is. Ha úgy csinálod meg, hogy mindegyik csinál is valamit, akkor már más a helyzet.
... (merthogy nekem is van saját objektumokból felépített portálmotorom :D ) nincs ennyi és remekül megy ;-)
Amik feltétlen kellenek: modul szülőosztály, abból származtatva a moduljaim (ilyen sorrendben is töltődnek be): portal, log, dblayer, user, template. (A dblayer az adboDB-re, a template pedig a smarty-ra egy réteg). Ezen kívül az éppen kívánt tevékenységhez tartozó modul (pl: guestbook, vagy gallery) és a tevékenység objektuma van még. Ez összesen: 12 körül van. Ezen felül ugye a formGenerator, de az csak form esetében kell, ahhoz van validator, stbstb...
Ha nagyon összeszámolom, akkor még mindig 20 alatt vagyok. (Csak az admin esetében van olyan, hogy mindent be kell tölteni, ha kíváncsi vagyok pl. az összes modul összes tevékenységére, mivel ezt az objektumokból mondon meg...)
Másik kérdéskör, hogy 1 nagy, vagy sok kis fájl ezt tudom mondani: én minden modult és minden tevékenységet külön fájlban tartok. Ami olyan objektum, ami önmagában nem fordulhat elő, csak egy tevékenységgel (pl. validator egy űrlaphoz, ami ugye egyedi és tudjuk, hogy hol fordul elő), azt még belerakom az objektum mellé.
Általában egy tevékenység (pl. modul: vendégkönyv, tevékenység: olvasás) kiszolgálására az alapfájlokon kívül csak 3 fájlt kell behúzni: vendégkönyv modul, olvasás tevékenység és az ehhez tartozó template (megjelenítési) fájl.
(kis csúsztatás azért van a dologban, mert jelen pillanatban ha a főoldalon mindenféle modulokhoz tartozó boxok - pl. a nap képe, szavazás, user stat, stb - van, akkor MÉG betöltheti azokat a modulokat is, de ezt már elkezdtem kiváltani megfelelő cache-eléssel. Ilyesfajta felépítéssel, mostmár lassan 2 évvel korábbi fejlődési szakaszban lévő, egyik egyetemi HÖK-által használt portál a főoldalon hírek, user stat, szavazás boxokkal 0.07 körül generál egy régi, egymagos intel P4-en, eAccelerator és APC nélkül. - a mostani rendszer cache-ből nyomná szinte az egészet.)
ööö... izé...
érthető volt, vagy túl gyors? Az biztos, hogy mindenki máshogy csinálja, de szerintem az alapelvek ugyanazok a gyorsaság érdekében:
- minél kevesebb fájlt behúzni
- (de) minél átláthatóbban szervezni a fájlokat és az objektumokat
- mindent, amit csak lehet, cache-elni
Ha ezen felül van kérdés, akár magánba is jöhet, ha nagyon eltér a témától...
tervezési minták, mvc
aláírom...
nagyon oo?
Én kb úgy képzeltem el, hogy van egy 'input' objektumom, amiből származik az editbox, passwordbox, hidden, memo, etc. Ezekből lesz majd egy loginform objektum, stb, stb, stb.
Szóval ha ilyen módon belegondolsz, akkor már logikusabbnak tűnik, ha azt mondom, lesz 50.
nem
ööö
naja..
ha már lúd
Annak nem sok értelmét látom, hogy egy egész vendégkönyvet mondjuk egy osztályba tenni, semmivel nem fog különbözni a hagyományos struktúrális megközelítéstől (kivéve, hogy írni kell egy 'class'-t a forráskód elejére).
Szeretném a lehető legportábilisebbé és újrafelhaszhatóvá tenni.
ps: kipróbáltam fastcgi-vel is a futtatást, LASSABB! lol? :D
Tök korrekt
Lehet, de lehet rajta javitani
Ekkor nem kell minden pl. inputtext-nel uj objektumot letrehozni, eleg csak a kulso tulajdonsagokat atadni az esetlegesen mar letezo egyetlen objektumodnak.
ömm
Kifejtenéd egy példával mondjuk?
Köszi.
Pehelysulyu minta
Ha a kulso tulajdonsagok mindig masok, akkor nem erdemes azokat kulon context-ben tarolni, erdemesebb atadni azokat egybol a - jelen esetben - printHtml()-nek.
Hajjaj...
Kicsit atgondoltam jobban
Igy hasznalhatnank valami ilyesmit:
Igazabol most megakadtam, nem latom a pehelysulyu minta elonyet. Valaki felvilagositana? :)
nem biztos
A fenti példád szinte alig különbözik egyetlen eljárástól, ami feldolgozza a kapott inputot, és kiír egy html-t.
Ez a switch-es megoldás pláne.
Mi van akkor, ha a $context->attributes['class'] üres érték? Bekerül a html-be, hogy class=''.
Fölösleges kód, fölöslegesen letöltendő byte-ok.
Az meg a másik, hogy mondjuk csinálsz egy switch-et:
textfield: <input type='text' class='$...' value='$...' id='$...'>
passwordfield: <input type='password' class='$...' value='$...' id='$...'>
stb.
Egymás után többször leírod, hogy class='$...', value='$...', nem optimális.
Nem ez a lenyeg
A lenyeg, hogy objektumokkal dolgozol, de megsem nonek a fejedre, mert minden tipusbol csak 1 van.
Az, hogy erdemes -e igy csinalni, nem tudom, mindenesetre jobb megoldas, mint ha minden elem kulon objektum lenne.
"objektumokkal dolgozni"
Üdv,
Felhő
nem értem mit akarsz..
& a függvény definícióban
Üdv,
Felhő
Nem kell, de nem is baj
Egyebkent tenyleg feleslegesnek tunik a fenti megoldas, agyuval verebre loves esete all fenn. De azert jo volt igy belegondolni (foleg vizsga elotti este :) )
PHP4 vs PHP5
Üdv,
Felhő
erre gondoltam én is...
a végén include optimalizálás
build folyamat
Üdv,
Felhő
apd
Top 5 esemény:
%Time (excl/cumm) (excl/cumm) (excl/cumm) Calls call s/call Memory Usage Name
--------------------------------------------------------------------------------------
42.9 0.01 0.05 0.00 0.02 0.01 0.03 10 0.0000 0.0000 0 require
14.3 0.00 0.00 0.00 0.00 0.00 0.00 22 0.0000 0.0000 0 define
4.8 0.00 0.01 0.00 0.00 0.00 0.00 34 0.0000 0.0000 0 sprintf
4.8 0.00 0.00 0.00 0.00 0.00 0.00 7 0.0000 0.0000 0 logerr
4.8 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0000 0.0000 0 mysqli->mysqli
Tehát az IO a nagy. Lehet ez ellen valamit tenni?
- memcached (hogyan include-olok?)?
- xcache (nem mukodik nekem)?
- egyéb ötlet?
A második, amin eléggé csodálkozom, az a define. Ez tényleg ennyire költséges művelet, elkerülési lehetőség van? (azon kívül, hogy nem használom)
re: apd
xcache nekem teljesen jol mukodott, de lehet hasznalni mast is (eacceleratort nem ajanlom, ugy tunik sok bugja van). Lenyegeben azon tudsz gyorsitani, hogy a) bent tartod a memoban a berantott fileokat (ilyet altalaban tudnak az opcode cache-ek); b) memoban tartod a lefordiott php kodokat (ilyet is tudnak az opcode cache-ek).
Egyeb otlet: sose nem probaltam, de talan ha ramdrivera rakod a php fileokat talan csokken egy kicsit az io. Opcode cache hasznalata erose javallott.
Ó, kipróbáltam :)
XCache-sel nem tudom mit kellene tennem, de amint beteszem, szór nekem mindenféle php errorokat, amiket még nem volt időm kinyomozni, így hát nem is próbálkoztam vele sokat.
eAcceleratort kipróbáltam, ami igen effektív volt: felére, vagy még kevesebbre csökkentette a render időt (a jelenlegi weblapomat átlag 0.045-ről átlag 0.012-re vitte le, ezt az osztályos mókát 0.01-ről 0.005-re)
Ugyanakkor az apd-vel néha összeakad, és conncetion reset by peer lesz belőle. Egyelőre éles lapokon nem használom az apd hívásokat, így talán ez elkerülhető.
Miket tudnék még kipróbálni? (az mmturck már abandoned, ha jól tudom).
Na ez meg aztán...
Mint azt korábban írtam, van egy weblapom, aminek a betöltési idejét sikerült lejjebb vinnem 0.045-ről 0.012 másodperc körülire (eAcceleratorral). Ezzel párhuzamosan ugyanezen a szerveren tesztelem ezt az osztályos mókát is, ami miatt a témát is nyitottam. Ott a 0.01-es render időt szorítottam le 0.005-re eAcc-cal.
A vicces az, hogy valamilyen okból kifolyólag a 0.005 váratlanul felugrik úgy 0.03-ra (általában napok kérdése). Az okát még nem sikerült kiderítenem, figyeltem a performanciát, load-ot, memóriát, szinte semmi változás nincs. Az éles weblapom betöltési ideje nem változott, csak az osztály-tesztelős kódé (mindkettőt ugyanaz a php, apache, mysql szolgálja ki - mindkettő http, tehát nem https). Ha megnézem APD-vel, hogy mi teszi ki az értelmezés nagy részét, akkor a file betöltést teszi első helyre, többnyire 30-45%-kal.
Miután nem találtam semmi okot a megnövekedett generálási időre, újraindítottam az alatta futó apache-ot.
És láss csodát: a render idő visszaesett 0.005-re.
Ennek meg mi lehet a magyarázata?
Milyen rendszer?