Raketentester: Tipps für die Verwendung von Array oder Objekt

Beitrag lesen

Ein allgemeiner Leitfaden, wann es sinnvoll ist, ein multidimensionales Array zuverwenden und wann ein resourcenfressendes Objekt, ist echt eine Hilfe

Da PHP-Variablen (Arrays, Hashes/„named arrays“, wie schon beschrieben) einerseits „alles außer typsicher“ sind, anderseits der Zugriff auf einen Array schneller, ist eine Klasse/Objekt das Mittel der Wahl wenn ich

  • via „setter“ Typsicherheit und/oder Plausibilität der Items sicher stellen will. (Dann sind die Items aber mit Sicherheit nicht „public“).
  • via getter Ausgaben unterschiedlich steuern will (da gabs erst neulich eine Diskussion, wo die Daten als Array oder JSON ausgegeben wurden, allerdings mit kruden Namen der Methoden.)

Ein Test der Zugriffsgeschwindigkeiten:

Ich habe mal versucht, einen fairen Test zu schreiben. Erzeugt wird ein Array, ein Hash („named array“) sowie jeweils ein simples Objekt, welches den Array bzw. Hash enthält. Aus dem Array/Objekt mit Array und aus dem Hash/Objekt mit Hash wird dann jeweils mit „gettern“ gelesen.

<?php

class oArr {
	var $arr = false;
	function __construct ( $arr ) {
		$this->setArr( $arr );
	}
	function setArr( $arr ) {
		$this->arr = $arr;
	}
	function getArr ( ) {
		return $this->arr;
	}
	function getItem ( $i ) {
		if ( isset( $this->arr[$i] ) ) {
			return $this->arr[$i];
		} else {
			return false;
		}
	}	
}

class oHash {
	var $hash = false;
	function __construct ( $hash ) {
		$this->sethash( $hash );
	}
	function setHash( $hash ) {
		$this->hash =  $hash;
	}
	function getHash ( ) {
		return $this->hash;
	}
	function getItem ( $s ) {
		if ( isset( $this->hash[$s] ) ) {
			return $this->hash[$s];
		} else {
			return false;
		}
	}		
}

$s     ='ABCDEFGHIJKLMNOPQRSTYUVWXYZ';
$items = 10000;
$max   = strlen( $s ) - 1;


$arr  = [];
$hash = [];
for ( $i=0; $i < $items; $i++ ) {
	$string = '';
	for ( $k=0; $k < rand(4, 8); $k++ ) {
		$string .= $s[ rand(0, $max ) ];
	}
	$arr[]         = $string;
	$hash[$string] = $i;
}

$Arr  = new oArr ( $arr );
$Hash = new oHash ( $hash ) ;

$start = microtime( true );
foreach ( $arr as $s ) {
    $dummy = $s;
}
$time = microtime( true ) - $start;
echo "foreach über gesamten Array ( $items Items ) : $time Sekunden " . PHP_EOL;

$time = microtime( true ) - $start;
for ( $i = 0; $i < $items; $i++ ) {
   	$dummy = $arr[$i];
}
$time = microtime( true ) - $start;
echo "for i über gesamten Array   ( $items Items ) : $time Sekunden " . PHP_EOL;

$time = microtime( true ) - $start;
for ( $i = 0; $i < $items; $i++ ) {
   	$dummy = $Arr->getItem( $i );
}
$time = microtime( true ) - $start;
echo "for i über Objekt           ( $items Items ) : $time Sekunden " . PHP_EOL;
echo "------------------------------------------------------------------------------------" . PHP_EOL;

$time = microtime( true ) - $start;
foreach ( $arr as $s ) {
   	$dummy = $hash[$s];
}
$time = microtime( true ) - $start;
echo "Alle Items des Hashes       ( $items Items ) : $time Sekunden " . PHP_EOL;

$time = microtime( true ) - $start;
foreach ( $arr as $s ) {
   	$dummy = $Hash->getItem( $s );
}
$time = microtime( true ) - $start;
echo "Alle Items des Hash-Objects ( $items Items ) : $time Sekunden " . PHP_EOL;

Ergebnis:

foreach über gesamten Array ( 10000 Items ) : 0.00083422660827637 Sekunden 
for i über gesamten Array   ( 10000 Items ) : 0.0027182102203369 Sekunden 
for i über Objekt           ( 10000 Items ) : 0.01047420501709 Sekunden 
------------------------------------------------------------------------------------
Alle Items des Hashes       ( 10000 Items ) : 0.01156210899353 Sekunden 
Alle Items des Hash-Objects ( 10000 Items ) : 0.018543004989624 Sekunden

Fazit:

  • Zugriff auf Array ist signifikant (Faktor 3.9) schneller als Objekt.
  • Allerdings ist der Unterschied „deutlich weniger signifikant“ (Faktor 1.6) bei einem Zugriff auf einen Hash(„named array“) im Verhältnis zu einen Objekt.