Opierając się na kodzie Quazzle, uruchomiłem następny kod (5.4.16 Windows 64 bity):
<?php
class SomeClass {
public $aaa;
public $bbb;
public $ccc;
}
function p($i) {
echo '<pre>';
print_r($i);
echo '</pre>';
}
$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage();
for ($i=0; $i<1000; $i++) {
$z = array();
for ($j=0; $j<1000; $j++) {
$z['aaa'] = 'aaa';
$z['bbb'] = 'bbb';
$z['ccc'] = $z['aaa'].$z['bbb'];
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);
$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage();
for ($i=0; $i<1000; $i++) {
$z = new SomeClass();
for ($j=0; $j<1000; $j++) {
$z->aaa = 'aaa';
$z->bbb = 'bbb';
$z->ccc = $z->aaa.$z->bbb;
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);
$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage();
for ($i=0; $i<1000; $i++) {
$z = new stdClass();
for ($j=0; $j<1000; $j++) {
$z->aaa = 'aaa';
$z->bbb = 'bbb';
$z->ccc = $z->aaa.$z->bbb;
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);
?>
I uzyskałem następny wynik:
arrays: 1.8451430797577
memory: 460416
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 1.8294548988342
memory: 275696
SomeClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 2.2577090263367
memory: 483648
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
Wniosek dla php 5.4
- Klasa jest szybsza niż Arrays (ale marginalnie).
- stdClass jest zła.
- Klasa zużywa mniej pamięci niż Arrays. (około 30-40% mniej !!)
ps: uwaga, jeśli klasa jest zdefiniowana, ale członkowie to członkowie, użycie tej klasy jest wolniejsze. Zużywa też więcej pamięci. Najwyraźniej sekret polega na zdefiniowaniu członków
Aktualizacja
Zaktualizowałem z php 5.4 do php 5.5 (5.5.12 x86 windows).
arrays: 1.6465699672699
memory: 460400
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 1.8687851428986
memory: 363704
SplFixedArray Object
(
[0] => aaa
[1] => bbb
[2] => aaabbb
)
arrays: 1.8554251194
memory: 275568
SomeClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 2.0101680755615
memory: 483656
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
Wniosek dla php 5.5
- W przypadku tablic PHP 5.5 jest szybsze niż PHP 5.4, w przypadku obiektów jest prawie takie samo
- Klasa jest wolniejsza niż Arrays dzięki optymalizacji PHP 5.5 i tablic.
- stdClass jest zła.
- Klasa nadal zużywa mniej pamięci niż Arrays. (około 30-40% mniej !!).
- SplFixedArray jest podobny do używania klasy, ale zużywa więcej pamięci.
Użyłem tego kodu do „profilowania” (1000 instancji, 1000 000 odczytów / zapisów):
function p($i) { echo '<pre>'; print_r($i); echo '</pre>'; } $t0 = microtime(true); for ($i=0; $i<1000; $i++) { $z = array(); for ($j=0; $j<1000; $j++) { $z['aaa'] = 'aaa'; $z['bbb'] = 'bbb'; $z['ccc'] = $z['aaa'].$z['bbb']; } } echo '<p>arrays: '.(microtime(true) - $t0); p($z); $t0 = microtime(true); for ($i=0; $i<1000; $i++) { $z = (object) null; for ($j=0; $j<1000; $j++) { $z->aaa = 'aaa'; $z->bbb = 'bbb'; $z->ccc = $z->aaa.$z->bbb; } } echo '<p>obj: '.(microtime(true) - $t0); p($z); echo '<p> phpversion '.phpversion();
Wyprowadza w moim hostingu LINUX to:
arrays: 1.1085488796234 Array ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) obj: 1.2824709415436 stdClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) phpversion 5.2.17
więc podsumowując: obiekty są wolniejsze nawet w PHP 5.2. Nie używaj obiektów, chyba że naprawdę potrzebujesz ich funkcji oop.
źródło
Używam kodu magallanes pod php 7.0.9:
arrays: 0.19802498817444 memory: 324672 Array ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) arrays: 0.18602299690247 memory: 132376 SomeClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) arrays: 0.1950249671936 memory: 348296 stdClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb )
I php 7.1.3 użytkownika:
arrays: 0.59932994842529 memory: 444920 Array ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) arrays: 0.72895789146423 memory: 164512 SomeClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) arrays: 0.61777496337891 memory: 484416 stdClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb )
źródło
$a=new stdClass(); $a->{1} = 1; $b=(array)$a;
get real ['1' => 1].skrypt magallanesa @ PHP 7.3.5
SomeClass Object
jest najszybszy i najlżejszy.Array
1.32x prędkość. 2. 70x pamięć.stdClass Object
1,65x prędkość. 2.94x pamięć.Surowe dane wyjściowe:
arrays: 0.064794063568115 memory: 444920 Array ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) arrays: 0.048975944519043 memory: 164512 SomeClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) arrays: 0.081161022186279 memory: 484416 stdClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb )
źródło
Dla każdego, kto nadal jest zainteresowany tym pytaniem :) Uruchomiłem kod Quazzle na PHP 7.1 Ubuntu x64 i otrzymałem tę odpowiedź:
arrays: 0.24848890304565 memory: 444920 Array ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) arrays: 0.23238587379456 memory: 164512 SomeClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) arrays: 0.24422693252563 memory: 484416 stdClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb )
Wniosek
Tablica zajmuje 4 (!) Pamięć niż obiekt klasy.
Obiekt klasy nieznacznie szybszy.
stdClass still evil © magallanes :)
źródło
Nie pokazałeś nam kodu, jak
$object->value
działa, ponieważ może być tak, że backend jest tablicą, w którym to przypadku teoretycznie użycie tablicy byłoby szybsze, ponieważ wymaga jednego wywołania funkcji mniej. Koszt wyszukiwania będzie prawdopodobnie ogromny w porównaniu z wywołaniem funkcji. Jeśli jest to zmienna, różnica będzie bardzo niewielka, ponieważ obiekty i tablice w PHP mają bardzo podobną implementację.Jeśli patrzysz na optymalizacje, będziesz musiał profilować, aby sprawdzić, gdzie większość czasu jest używana. Podejrzewam, że zmiana obiektów na tablice nie zrobi większej różnicy.
źródło
Widzę, że to trochę stary post, więc pomyślałem, że go zaktualizuję. oto moje kody i statystyki, zrobione na Zend CE 5.3.21 Próbowałem przetestować całość, zapisując informacje i wycofując je.
V1: zajmuje 0,83 sek
for ($i=1; $i<1000000; $i++) { $a = get_one(); $b = $a[0]; $b = $a[1]; } function get_one() { return array(1,1); }
V2: zajmuje 3,05 sek
for ($i=1; $i<1000000; $i++) { $a = get_one(); $b = $a->v; $b = $a->k; } function get_one() { $ret = new test(); $ret->v = 1; $reb->k = 1; return $ret; } class test { public $v; public $k; }
V3: zajmuje 1,98 sekundy (zwróć uwagę, że konstruktor poprawia wydajność)
for ($i=1; $i<1000000; $i++) { $a = get_one(); $b = $a->v; $b = $a->k; } function get_one() { return new test(1,1); } class test { public $v; public $k; public function __construct($v, $k) { $this->v = $v; $this->k = $k; } }
źródło
Zawsze możesz sprawdzić kod źródłowy PHP pod kątem takich mikro-funkcji.
Ale na pierwszy rzut oka żadne działanie ['value'] nie będzie szybsze, ponieważ PHP musi wykonać Lookup, gdzie znaleźć ['value'], nawet jeśli wyszukiwanie hashtable powinno być O (1), to nie jest gwarantowane. Korzystanie z indeksu tekstowego wiąże się z większym narzutem.
Jeśli obiekt zawiera tylko 1 zmienną, do której chcesz uzyskać dostęp, czyli wartość, użycie obiektu wymaga większego obciążenia.
źródło
Cóż, zaciekawiło mnie dzisiaj w oparciu o benchmark @magallanes, więc nieco go rozszerzyłem. Podkręciłem niektóre pętle for, aby naprawdę podkreślić luki między elementami. Działa na Apache 2.4, mod_php i PHP 7.2.
Oto tabela podsumowująca, aby ułatwić wyniki:
+---------------------------+---------+-----------------+ | Test | Memory | Time | +---------------------------+---------+-----------------+ | Array | 2305848 | 9.5637300014496 | | stdClass | 2505824 | 11.212271928787 | | SomeClass | 164920 | 3.9636149406433 | <-- * | AnotherClass | 2563136 | 10.872401237488 | | SetterClass | 905848 | 59.879059791565 | | SetterClassDefineReturn | 905792 | 60.484427213669 | | SetterClassSetFromParam | 745792 | 62.783381223679 | | SetterClassSetKeyAndParam | 745824 | 72.155715942383 | +---------------------------+---------+-----------------+ * - Winner winner chicken dinner
Poniżej znajduje się zmodyfikowany skrypt. Chciałem przetestować właściwości ustawień metodami i zdefiniować typy. Byłem bardzo zaskoczony, gdy odkryłem, że użycie metod ustawiających dodaje znaczącego trafienia do kodu. Teraz przyznano, że jest to bardzo specyficzny test wydajności, w którym wiele aplikacji nawet tego nie osiągnie. Ale jeśli masz witrynę, która obsługuje 1000 / reqs / sekundę z 1000 klas, które są używane z tysiącami obiektów, możesz zobaczyć, jak może to wpłynąć na wydajność.
<?php set_time_limit(500); class SomeClass { public $aaa; public $bbb; public $ccc; } class AnotherClass { } class SetterClass { public $aaa; public $bbb; public $ccc; public function setAAA() { $this->aaa = 'aaa'; } public function setBBB() { $this->bbb = 'bbb'; } public function setCCC() { $this->ccc = $this->aaa.$this->bbb; } } class SetterClassDefineReturn { public $aaa; public $bbb; public $ccc; public function setAAA():void { $this->aaa = 'aaa'; } public function setBBB():void { $this->bbb = 'bbb'; } public function setCCC():void { $this->ccc = $this->aaa.$this->bbb; } } class SetterClassSetFromParam { public $aaa; public $bbb; public $ccc; public function setAAA(string $val): void { $this->aaa = $val; } public function setBBB(string $val): void { $this->bbb = $val; } public function setCCC(string $val): void { $this->ccc = $val; } } class SetterClassSetKeyAndParam { public $aaa; public $bbb; public $ccc; public function set(string $key, string $val): void { $this->{$key} = $val; } } function p($i) { echo '<pre>'; print_r($i); echo '</pre>'; echo '<hr>'; } $t0 = microtime(true); $arraysOf=[]; $inicio=memory_get_usage(); for ($i=0; $i<1000; $i++) { $z = new SomeClass(); for ($j=0; $j<10000; $j++) { $z->aaa = 'aaa'; $z->bbb = 'bbb'; $z->ccc = $z->aaa.$z->bbb; } $arraysOf[]=$z; } $fin=memory_get_usage(); echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>'; echo '<p>Memory: '.($fin-$inicio).'</p>'; p($z); $t0 = microtime(true); $arraysOf=[]; $inicio=memory_get_usage(); for ($i=0; $i<5000; $i++) { $z = new AnotherClass(); for ($j=0; $j<5000; $j++) { $z->aaa = 'aaa'; $z->bbb = 'bbb'; $z->ccc = $z->aaa.$z->bbb; } $arraysOf[]=$z; } $fin=memory_get_usage(); echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>'; echo '<p>Memory: '.($fin-$inicio).'</p>'; p($z); $t0 = microtime(true); $arraysOf=[]; $inicio=memory_get_usage(); for ($i=0; $i<5000; $i++) { $z = new SetterClass(); for ($j=0; $j<5000; $j++) { $z->setAAA(); $z->setBBB(); $z->setCCC(); } $arraysOf[]=$z; } $fin=memory_get_usage(); echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>'; echo '<p>Memory: '.($fin-$inicio).'</p>'; p($z); $t0 = microtime(true); $arraysOf=[]; $inicio=memory_get_usage(); for ($i=0; $i<5000; $i++) { $z = new SetterClassDefineReturn(); for ($j=0; $j<5000; $j++) { $z->setAAA(); $z->setBBB(); $z->setCCC(); } $arraysOf[]=$z; } $fin=memory_get_usage(); echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>'; echo '<p>Memory: '.($fin-$inicio).'</p>'; p($z); $t0 = microtime(true); $arraysOf=[]; $inicio=memory_get_usage(); for ($i=0; $i<5000; $i++) { $z = new SetterClassSetFromParam(); for ($j=0; $j<5000; $j++) { $z->setAAA('aaa'); $z->setBBB('bbb'); $z->setCCC('aaabbb'); } $arraysOf[]=$z; } $fin=memory_get_usage(); echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>'; echo '<p>Memory: '.($fin-$inicio).'</p>'; p($z); $t0 = microtime(true); $arraysOf=[]; $inicio=memory_get_usage(); for ($i=0; $i<5000; $i++) { $z = new SetterClassSetKeyAndParam(); for ($j=0; $j<5000; $j++) { $z->set('aaa', 'aaa'); $z->set('bbb', 'bbb'); $z->set('ccc', 'aaabbb'); } $arraysOf[]=$z; } $fin=memory_get_usage(); echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>'; echo '<p>Memory: '.($fin-$inicio).'</p>'; p($z); $t0 = microtime(true); $arraysOf=[]; $inicio=memory_get_usage(); for ($i=0; $i<5000; $i++) { $z = new stdClass(); for ($j=0; $j<5000; $j++) { $z->aaa = 'aaa'; $z->bbb = 'bbb'; $z->ccc = $z->aaa.$z->bbb; } $arraysOf[]=$z; } $fin=memory_get_usage(); echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>'; echo '<p>Memory: '.($fin-$inicio).'</p>'; p($z); $t0 = microtime(true); $arraysOf=[]; $inicio=memory_get_usage(); for ($i=0; $i<5000; $i++) { $z = []; for ($j=0; $j<5000; $j++) { $z['aaa'] = 'aaa'; $z['bbb'] = 'bbb'; $z['ccc'] = $z['aaa'].$z['bbb']; } $arraysOf[]=$z; } $fin=memory_get_usage(); echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>'; echo '<p>Memory: '.($fin-$inicio).'</p>'; p($z);
A oto wyniki:
Time Taken (seconds): 3.9636149406433 Memory: 164920 SomeClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) ----- Time Taken (seconds): 10.872401237488 Memory: 2563136 AnotherClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) ---- Time Taken (seconds): 59.879059791565 Memory: 905848 SetterClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) ---- Time Taken (seconds): 60.484427213669 Memory: 905792 SetterClassDefineReturn Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) ---- Time Taken (seconds): 62.783381223679 Memory: 745792 SetterClassSetFromParam Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) ---- Time Taken (seconds): 72.155715942383 Memory: 745824 SetterClassSetKeyAndParam Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) ---- Time Taken (seconds): 11.212271928787 Memory: 2505824 stdClass Object ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb ) ---- Time Taken (seconds): 9.5637300014496 Memory: 2305848 Array ( [aaa] => aaa [bbb] => bbb [ccc] => aaabbb )
źródło
Jeśli tablice i klasy mają taką samą wydajność, myślę, że użycie obiektów predefiniowanych klas do przechowywania / przekazywania danych biznesowych sprawiłoby, że nasz program byłby bardziej logiczny, a kod bardziej czytelny.
Dzisiaj, przy nowoczesnych ideach, takich jak Eclipse, Netbean ... bardzo wygodnie jest wiedzieć, jakie informacje niosą obiekty (predefiniowanej klasy), ale tablice nie są takie
Np .: Z tablicą
function registerCourse(array $student) { // Right here I don't know how a $student look like unless doing a print_r() or var_dump() .... }
Z przedmiotem
class Studen { private $_name, $_age; public function getAge() {} public function getName() {} .. } function registerCourse(Studen $student) { // Right here I just Ctrl+Space $student or click "Student" and I know I can get name or age from it ... }
źródło