ot Andrey(20-12-2002)

reiting (4)   [ dobre ]  [ zle ]

Printer Friendly Variant za otpechatvane

file_get_contents()

Pone do momenta na izlizane na 4.3.0 sa mi poznati 3 nachina za izvlichane sudurzhanieto na fail ot diska ili vuobshte na fail, kogato se izpolzva pototsi.
Primer 1
$content = implode('', file($fname));
Komentar :
Tova e edin ot nai-chesto izpolzvanite metodi. Mozhe da go sreshtnete v mnogo skriptove. Dostatuchno burz. Mozhe da uchastva v izraz.
Nedostatutsi :
V povecheto sluchai tozi kod shte raboti, no ima izklyucheniia. Do versiia 4.3.0 funktsiiata file() ne e binary-safe. T.e. za tekstovi failove niama da ima problemi. Problemite vuznikvat vuv momenta, v koito reshite da otvariate fail, koito sudurzha simvola na '\0'. Nachin za izbiagvane : vzh. Primer 2

Primer 2
$fd = fopen($fname, 'r'); // za uindous triabva da e 'rb'
 $content = fread($fd, filesize($fname));
 fclose($fd);
 $content = implode('', file($fname));
Komentar :
Tova e edin ot po-malko izpolzvan metod. Izbiagva problema na predishniiat metod za versii < 4.3.0 . Skorostta mu e niakude okolo tazi na predishniiat metod, no mislia malko po-baven.
Nedostatutsi :
Mozhe bi edinstveniiat mu nedostatuk e, che se pishe na 3 reda kod i ne mozhe da bude chast ot izraz, kakto e pri predishniiat metod.

Primer 3
ob_start();
 readfile($fname);
 $content = ob_get_contents();
 ob_end_clean();
 $content = implode('', file($fname));
Komentar :
Tova e edin ot malko izpolzvan metod. Riadkost e da go sreshtnete v skript. Izpolzva se tehnikata na buferirane na izhoda, koiato ne e mnogo populiarna. Opredeleno nai-burziiat ot vsichki pokazani do momenta metodi, no za smetka na tova se izpolzvat poveche resursi (glavno pamet). Nedostatutsi :
Kakto i Primer 2, ne mozhe da uchastva v izraz. Ne vuv vsichki sluchai e nedostatuk, no ako pametta vi e kut, togava ne Vi go preporuchvam.

Primer 4 : Novata funktsiia
$content = file_get_contents();
Komentar :
Tazi funktsiia se iaviava evolyutsionna, zashtoto vse pak ne e hubavo za skriptov ezik, koito se izpolzva shiroko za izvlichane sudurzhanieto na fail da se polzvat nakup nai-malko 2 funktsii. Tova shte bude veche nai-burziiat metod za chetene pri tova e binary-safe. Kato vutreshnost funktsiiata mnogo napodobiava readfile(), no vrushta rezultata vmesto da go izkarva na izhoda.

version_compare() i debugvane

Funktsiiata se izpolzva sa sravnenie na dva niza, koito sudurzhat versii po PHP standarta.
Primer 5
<?php
 $Debug_level = 2|4|8|16|32|1024;
 
 if (($Debug_level & 1024) && version_compare(PHP_VERSION , "4.3.0-dev",'<')) {
         $Debug_level -= 1024;
 }
 define('DEBUG_MODE', $Debug_level);
 error_reporting(E_ALL);
 
 ...
 ...
 (DEBUG_MODE & 1024) && log_printf("[Elapsed in %s::%s = %2.5fs]\n",
 __CLASS__, __FUNCTION__, $timer->elapsed());
 ?>
Tozi primer pokazva kak mozhe da zashtitite kod ot izpulnenie na niakoi versii na PHP. V sluchaia na versii, koito sa predi 4.3.0-dev. Tazi zashtita se nalaga zashtoto predefiniranite konstanti __CLASS__ i __FUNCTION__ se poiaviavat prez April 2002g. vuv 4.3.0-dev.
Za chast ot chitatelite polovinata kod mozhe da e nerazbiraem. Osobeno posledniia red. Izpolzva se pobitovo sravnenie (aritmetichen OR). Tova e tehnika shiroko izpolzvana ot programistite na C. Dava vuzmozhnost samo s edna operatsiia da se proveri dali e triabva da se izpishe dadena debug informatsiia.
Primer 6
<?php
 (DEBUG_MODE & 5) && printf("Entering parsing and saving mode at : ".microtime()."\n");
 ?>
V tozi sluchai se proveriava dali debug nivoto e 1 ili 4 printf() se izpulniava samo kogato e izpulneno da e "vdignato" nivo i/ili nivo 4. V sluchaia nivo 1 oznachava vsichki suobshteniia, a 4 - informatsiia za vremeto za izpulnenie.
Plyus na tozi metod e che se subira na 1 red.
Primer 7
<?php
 if ((DEBUG_MODE & 4) || (DEBUG_MODE & 1)) {
         printf("Entering parsing and saving mode at : ".microtime()."\n");
 }
 ?>
Kakto se vizhda ekvivalenten if operator zaema nai-malko 2 reda. Razbira se mozhe da se zapishe na 1 red, no tozi zapis shte e protiv vsiakakva konventsiia za zapisvane na tozi operator. Razbira se moga da bude obvinen, che metoda koito polzvam e nerazbiraem i oburkvasht, dori poniakoga zagroziavasht koda, no opredeleno pesti redove vidim kod v redaktora. A ako kato sviknesh s nego ne ti pravi vpechatlenie. Podobno da vechniiat disput kude da se pishe otvariashtata liava skoba.

array_shift($ar)

Tazi funktsiia vrushta purviiat element ot masiva $ar kato go premahva ot tam i prenarezhda masiva. Ako tursite proizvoditelnost i ne se nuzhdaete ot tova elementite vi v edin masiv da sa s indeksi zapochvashti ot nula, to ne izpolzvaite tazi funktsiia. Za razlika ot Perl i Python, tuk PHP e baven. Silno namalenata proizvoditelnost e sledstvie ot fakta, che vsichki elementi na masiva triabva da budat obhodeni i tehnite indeksi da budat prenomerirani ot 0. Pochti nikakvo e zabavianeto ot preheshiraneto.
Edno vuzmozhno reshenie samo vednuzh da si podredite masiva po indeksi (posledovatelni), da pravite unset() na purviiat element ot masiva, kato izpolzvate pomoshtna promenliva.
Primer 7
<?php
 $ar = array(1,1,2,3,5,8,13,21,34,55);
 $first_elem_idx = 0;
 $elem = $ar[$firs_elem_idx]; // 1
 unset($ar[$firs_elem_idx++]);
 
 $elem = $ar[$firs_elem_idx]; // 1
 unset($ar[$firs_elem_idx++]);
 
 $elem = $ar[$firs_elem_idx]; // 2
 unset($ar[$firs_elem_idx++]);
 ?>

do..while

do..while e tsikul s postuslovie. Toi se izpolzva dosta po-riadko ot while. Dori dosta chesto se praviat trikove predi while za da se emulira na praktika tsikula s postuslovie. Tuk obache shte spomena edna vuzmozhnost, na tazi konstruktsiia, koiato namiram za mnogo udobna :
Primer 8
<?php
 do {
         if ($i < 5) {
                 print "i is not big enough";
                 break;
         }
         $i *= $factor;
         if ($i < $minimum_limit) {
                 break;
         }
         print "i is ok";
         
         ...process i...
 } while(0);
 ?>
Primera e vzet ot dokumentatsiiata na PHP. Tozi tsikul se izpulniava samo vednuzh, vsushtnost tova e psevdotsikul, zashtoto se izpolzva samo zashtoto v nego sa dostupni break i continue;. Vsushtnost continue; ne se izpolzva zashtoto efekta e ekvivalenten na break - izlizane ot bloka. Mozhe da se oprilichi na izklyucheniiata poznati na niakoi ot C++, Java, Object Pascal. Razlikata e, che obrabotkata pri izklyuchitelnata situatsiia v povecheto sluchai se pravi v tialoto na tsikula predi izpulnenieto na prehoda.

array_map()

Osven obiknovennoto si povedenie, tazi funktsiia ima neshto interesno skrito v neia :
Primer 9
<?php
 $a = array(1, 2, 3, 4, 5);
 $b = array("one", "two", "three", "four", "five");
 $c = array("uno", "dos", "tres", "cuatro", "cinco");
 
 $d = array_map(null, $a, $b, $c);
 print_r($d);
 /*
 Izhoda e :
 Array
 (
 [0] => Array
 (
 [0] => 1
 [1] => one
 [2] => uno
 )
 
 [1] => Array
 (
 [0] => 2
 [1] => two
 [2] => dos
 )
 
 [2] => Array
 (
 [0] => 3
 [1] => three
 [2] => tres
 )
 
 [3] => Array
 (
 [0] => 4
 [1] => four
 [2] => cuatro
 )
 
 [4] => Array
 (
 [0] => 5
 [1] => five
 [2] => cinco
 )
 )
 */
 ?>
Kakto se vizhda, ako purviiat parametur e NULL tazi funktsiia smesva elementite na podadenite i kato parametri masivi v tozi, koito se vrushta. Purviiat parametur se izpolzva za predavane na ime na "callback" funktsiia.

Malko dumi za proizvoditelnost

Za vseki, koito e reshil da trugne po putia na OOP v PHP e iasno, che koda mu shte bude po-baven. Vse pak ako tolkova silno zhelaete ili se nuzhdaete ot vsiaka milisekunda to togava ima kakvo da napravite po vuprosa
Primer 10
<?php
 class CObject {
         var $property;
         
         function CObject() {
                 $this->property = 0;
         }
 }// class CObject
 
 class CLongLoop extends CObject {
         function CLongLoop() {
                 parent::CObject();
         }
         
         function do_long_loop_slow($how) {
                 for ($i=0; $i < $how; $i++) {
                         $this->property++;
                 }
         }
         
         function do_long_loop_fast($how) {
                 $this_property = &$this->property;
                 for ($i=0; $i < $how; $i++) {
                         $this_property++;
                 }
         }
 }// class CLongLoop
 
 $long_loop_obj = new CLongLoop();
 echo microtime()."<br>\n";
 $long_loop_obj->do_long_loop_slow(100000);
 echo microtime()."<br>\n";
 $long_loop_obj->do_long_loop_fast(100000);
 echo microtime()."<br>\n";
 
 echo microtime()."<br>\n";
 $long_loop_obj->do_long_loop_slow(100);
 echo microtime()."<br>\n";
 $long_loop_obj->do_long_loop_fast(100);
 echo microtime()."<br>\n";
 
 /*
 Izhod na mashina : Pentium 3 Celeron 700MHz, 256 RAM
 
 Pri 100 000 iteratsii
 
 0.00246600 1040316935
 0.32363900 1040316935
 0.54043900 1040316935
 
 -=-=-=
 Purvi nachin : ~ 0.32s
 Vtori nachin : ~ 0.22s
 
 
 Pri 100 iteratsii :
 0.38567500 1040317294
 0.38614000 1040317294
 0.38642200 1040317294
 Purvi nachin : ~ 0.00047s
 Vtori nachin : ~ 0.00028s
 
 */
 ?>
Kakto se vizhda vtoriiat nachin e s okolo 30% po-burz. Vse pak triabva da imate v predvid, che tsikula se izvurta 100 000 puti. Tova ne e nikak malko. Za tsikli s poriadutsi po-malko na broi iteratsii zabavianeto e neznachitelno. Razbira se, ako v tsikula se izpolzvat poveche "nelokalni" promenlivi - chlen-promenlivi na klasa skorostta pada proportsionalno na tehniiat broi. Zashto se poluchava takava razlika? CHetete v sledvashtata tochka.

Navutre v nachina na rabota na Zend Engine

Razlikata se poluchava ot spetsifikata na interpretatsiia na PHP skriptovete. Ako ne izpolzvate "kesh" za kod, to ZendEngine
1)Zarezhda skripta ot diska
2)Pravi analiz
2.1)Sintaktichen
2.2)Semantichen, kato ednovremenno s nego se generira mezhdinen kod
3)Izpulniava generiraniiat mezhdinniiat kod
Mezhdinniiat kompiliraniiat mezhdinen kod e tova, koeto populiarnite produkti kato ZendCache i PHPAccelerator keshirat. V izvestna stepen mezhdinniiat kod mozhe da se i se optimizira ot tezi produkti. Taka izpulnenieto na skriptove mozhe da se uskori znachitelno.
Vse pak neka da kazha neshto poveche za mezhdinniiat kod. Tova e asemblera na PHP. Instruktsiite sa podobni na tezi v asemblerite za razlichni protsesori, no suobrazeni sus spetsifikata na "virtualnata mashina". Opkodovete sa nad 110 vuv ZE1 i okolo 140 vuv ZE2. Kogato edno prisvoiavane se prevrushta v mezhdinen kod to se zamestva s niakolko opkoda. Zarezhda se adresa na promenlivata, na koiato se prisvoiava stoinost. Tursi se po ime(niz) v hesha na tekushto aktivnata funktsiia (bila tia i main() ). Tozi adres se zarezhda vuv vremenna promenliva. Sled tova ako na promenlivata se prisvoiava promenliva se zarezhda neiniiat adres, i purvata promenliva stava referentsiia (da ne se burka s ukazatel) kum vtorata. Ako se prisvoiava izraz, to se izvlicha rezultata ot vremennata promenliva v koiato predi tova e zapisan. Vsichko tova mozhe da izglezhda malko slozhno, no na praktika ne e taka.
Tazi teoriia pomaga da se obiasneni "Primer 10". Kogato izpolzvat $this->property , se zarezhda adresa na $this ot hesha na izvestnite promenlivi v tekushtiiat metod, sled tova v hesha sudurzhasht chlen-promenlivite na klasa se izvurshva tursene po niz, za da se nameri adres na $this->property. Kakto se vizhda razlikata, e che pri chlen promenlivi se izvurshva edno tursene poveche. Vse pak $this e edna ot purvite deklarirani promenlivi vuv vseki metod i turseneto e po-burzo.
Ako produlzhim s razsuzhdeniiata na baza na gornata teoriia mozhe da se obiasni zashto sa vuzmozhno tova :
Primer 11
<?php
 $foo = 'bar';
 $bar = 'ok we got it';
 echo $$foo; // ok we got it
 echo $foo(); // In bar()
 
 function bar() {
         return "In bar()\n";
 }
 ?>
Sudurzhanieto na $foo se izpolzva pri turseneto v hesha s promenlivite i se izpisva sudurzhanieto na $bar. Pri funktsiiata e analogichno, turseneto stava v hesha s deklariranite funktsii. Primera mozhe da se razshiri dori i za suzdavane na instantsiia na klas

Literatura:

  1. Dokumentatsiiata na PHP
  2. Razlichni materiali ot Internet
  3. Dev forumite na PHP
  4. Statiia na Derick Rethans za tova kak raboti ZE


<< CHesto zadavani vuprosi za Squid (chast 2) | Kak da nakareme konzolata da shtadi ochite ni. >>