Tutorials

PHP Performance

Wat is nu snel en wat niet? Hier de tests!

Pagina 1

Inleiding

In php kun je veel dingen op meerdere manieren implementeren. Het één is sneller dan het ander.

Zie ook de tutorial van Rick voor een implementatie in variabelen, arrays en output.

Ik wil de volgende dingen behandelen:
- Functies
- Includes
- Objecten
- Replace
- ?? Nog meer onderzoek?

Changelog

- [2007-07-19] Tests toegevoegd mbt externe bestanden.
Pagina 2

Metingen

Ik voer de metingen uit met behulp van het DIV_TIMER object dat ik heb ontwikkeld. Dit object is hier te vinden.

Ik zal proberen om de metingen meerdere keren uit te voeren. Ik zal ook proberen conclusies uit de metingen te trekken.

Opmerkingen
Deze tutorial zal een groeiproces ondervinden. Ik zal de tutorial stap voor stap uitbreiden. Verwacht dus niet in één keer een hele lap tekst, dat komt. Ik zou ook graag vernemen als je bepaalde punten getest zou willen hebben, dan kan ik kijken of ik dat voor je wil testen!

Tevens heb ik alles getest met een cpu die idle is. Bij het opvragen van pagina's met veel data (10000 x echo) heb ik de pagina compleet laten laden en de cpu tot rust laten komen alvorens een refresh te doen. De CPU belasting heb ik in de gaten gehouden met behulp van statbar.
Pagina 3

Losse tests

String contaminatie of argumenten

Ik las zojuist in een post dat een echo met argumenten sneller zou zijn dan een echo met die met behulp van punten aan elkaar is geplakt. Zien is geloven natuurlijk!


<?

include('DIV_TIMER.class.php');

$oTimer = new DIV_TIMER('external_files.txt');

for($i=0; $i<10000; $i++)
{
	echo 'Een string'.' aan elkaar plakken'.' met behulp van contaminatie '.$i;
}

$oTimer->stop_timer();
echo $oTimer->get_time();

?>


Voor de test met argumenten heb ik de punt vervangen door een komma. Ik heb elk script 20 keer gerequest.


Alleen een punt tussen string en var: 0.087213981151582
Contaminatie (gebruik van punten): 0.092773115634919
Argumenten (gebruik van komma's): 0.072976529598236


Conclusie
Hier lijkt een miniem verschil te zijn, echter heb ik de contaminatie test nogmaals gedraaid, toen kwam ie op 0.06xxx. Ik kan maar één redelijke conclusie trekken. Het maakt niet uit hoe je string opgebouwd wordt. Een echo minder geeft meer performance winst dan het gebruik van een . of een ,
Pagina 4

Externe bestanden

Er zijn verschillende redenen om je applicatie uit meerdere bestanden te laten bestaan. Zoals overzicht of script die door derden worden gebouwd. Elk script dient echter weer apart geinclude te worden in je applicatie. Dit kan gebeuren door middel van include of require (_once).

Ik wil hier gaan testen welke invloed het heeft om te includen door overvloedig te includen. Ik hoop hieruit een aantal interessante conclusies te kunnen trekken.

Lege includes
Allereerst heb ik een map gemaakt met 100 lege php bestanden. Welke ik op verschillende manieren wil gaan includen.


<?
include('DIV_TIMER.class.php');

$oTimer = new DIV_TIMER('external_files.txt');

for($i=0; $i<100; $i++)
{
	include('empty_testfiles/file_'.$i.'.php');
}

$oTimer->stop_timer();
echo $oTimer->get_time();
?>


In dit stukje code heb ik steeds de include vervangen door include_once, require of require_once. De resultaten worden gecached in de external_files.txt. Hier de uitslag naar 20 requests (maal 100 includes):

De tijd geeft overigens de tijd aan voor de 100 includes in totaal (in seconden).

lege loop: 0.00009784698486
include: 0.021689617633819
include_once: 0.022119426727295
require: 0.021599543094634
require_once: 0.020833826065063


Conclusie
Zoals te zien zijn de verschillen erg minimaal bij lege bestanden. Wat me opviel bij het doen van de tests, dat apache het nog sterk optimaliseerd. De eerste set includes die ik deed was maarliefst 0,06s trager gemiddeld gezien over 20 requests. Op zich niet zo heel denderend, maar wel ongeveer 30%!!

Overigens mag het voor zichzelf spreken dat includes het geheel wel vertragen, ten opzichte van geen includes.

Gevulde includes
Daar alle content die er in een include staat ook geinitialiseerd wordt, is het van belang om ook een realistische test uit te voeren met gevulde bestanden. De vraag is echter, wat zet je in zo'n bestand. Ik zou kunnen werken met output (echo), functies of classes. Of gewoon een losse berekening.

Ik maak eerst een map met weer 100 bestanden waarin de volgende regel staat:

<?
echo 'PHPhulp performance test tutorial. Testing the php performance of some output.<br/>';
?>


Verder gebruik ik weer dezelfde code als in de voorgaande test. Ik zal nu echter output terugkrijgen. Ik heb tevens een loopje laten draaien met de echo regel van hierboven erin.
Dit zijn de resultaten, wederom na 20 requests.


lege loop: 0.00009784698486
echo loop: 0.00042909383773805
include: 0.026817965507506
include_once: 0.026759719848634
require: 0.02636524438858
require_once: 0.025042641162872


Concluse
We zien een lichte toename in de parsetijd van het script, over de gehele linie. Echter zit er geen uitschieter bij. De keuze van een include methode heeft een verwaarloosbare invloed op de performance van je site. Het includen in zijn geheel heeft echter zeker wel invloed op je script. Minder includes betekend meer performance. Zeker ook als je het vergelijkt met de echo loop. Deze is een stuk trager dan een lege loop. Echter is de include loop een veel grotere vertragende factor dan de echo regel.

Voor veel applicaties zal dit niet opgaan omdat in verschillende bestanden verschillende output wordt gegenereerd. Echter bibliotheken kunnen beter zoveel mogelijk in één bestand gegooid worden voor optimale performance (dan ben je wel op de milisecondes aan het letten, maar met 1000 requests per minuut zou dit toch een voordeel kunnen zijn).


Externe classes
Omdat het veel voorkomt dat ieder klasse zijn eigen bestand krijgt, is het leuk om te kijken hoe de performance zich verhoudt met losse bestanden of een library file.

Ik heb 100 bestanden gegenereerd met de volgende code:

<?
class TestObject[OBJNR]
{
	var $_strName;
	var $_strVal;
	
	function TestObject[OBJNR]($strName, $stVal)
	{
		$this->_strName = $strName;
		$this->_strVal = $strVal;
	}
	
	function get_name()
	{
		return $this->_strName;
	}
	
	function get_value()
	{
		return $this->_strVal;
	}
}
?>


Ik ga de tests alleen uitvoeren met een include statement.
Na 50 request komt de include tijd van 100 object files op 0.024083886146544 seconden. Dit is ongeveer gelijk aan het echo statement.

Ik ga nu een gecompileerde versie bouwen en deze in één keer includen.
De includetime bedraagt dan:0.0064766407012939 seconden.
Dit is ongeveer 4x sneller dan alle includes los te doen.

Conclusie
Het is lonend om een library te compileren vanuit al je classes. Absoluut scheelt het niet veel, maar wederom, procentueel gezien kan hierdoor een flinke winst gerealiseerd worden. Ook require_once requisten kun je hiermee vermijden waardoor je code toch weer een tik sneller wordt.

Reacties

0
Nog geen reacties.