Objetos PHP vs Arrays - comparação de desempenho durante a iteração

93

Eu tenho uma grande quantidade de objetos PHP para uma rede neural para a qual preciso iterar e realizar algumas contas. Eu queria saber se seria melhor usar uma matriz associativa em vez de instâncias de classes.

Estou lidando com 3640objetos circundantes e repetindo 500tempos (na melhor das hipóteses) além disso, qualquer micro-otimização ajuda muito. Seria inevitavelmente mais rápido de fazer do $object['value']que $object->value?

Edit: Então, eles são os mesmos. Mas acho que haveria uma pequena sobrecarga para o construtor? De qualquer forma, não acho que quero trocar minhas belas classes por matrizes sujas: P

Louis
fonte

Respostas:

65

Com base no código do Quazzle, executei o próximo código (5.4.16 windows 64bits):

<?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);  
?>

E obtive o próximo resultado:

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
)

Conclusão para php 5.4

  1. A classe é mais rápida do que Arrays (mas marginalmente).
  2. stdClass é mau.
  3. A classe usa menos memória do que os Arrays. (cerca de 30-40% menos !!)

ps: como uma nota, se a classe é definida, mas os membros então, o uso desta classe é mais lento. Ele também usa mais memória. Aparentemente o segredo é definir os membros

Atualizar

Eu atualizei do php 5.4 para o 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
)

Conclusão para php 5.5

  1. Para arrays, o PHP 5.5 é mais rápido que o PHP 5.4, para objetos é praticamente o mesmo
  2. Class é mais lento do que Arrays graças à otimização do PHP 5.5 e arrays.
  3. stdClass é mau.
  4. A classe ainda usa menos memória do que os Arrays. (cerca de 30-40% menos !!).
  5. SplFixedArray é semelhante a usar uma classe, mas usa mais memória.
Magalhães
fonte
Muito bem, bom senhor. Seria interessante expandir isso para arrays aninhados, etc. Sites interessantes para outro desempenho de PHP: phpbench.com php-benchmark-script.com, mas gosto que você tenha usado memória também.
Heath N
2
Com o PHP7, a diferença entre arrays e objetos se tornou mais significativa. Seu script mostra uma diferença de 30% de tempo de execução e 60% de memória. Essa é apenas minha máquina, mas como regra prática: não use arrays como structs. Em vez disso, use objetos :)
KingCrunch
Os objetos são diferentes das classes neste caso?
Matt G de
Marcando isso na esperança de qualquer atualização do PHP7. E talvez o próximo PHP8, quando aplicável. @magallanes
s3c
8

Usei este código para "criação de perfil" (1000 instâncias, 1000.000 leituras / gravações):

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();

Ele produz no meu LINUX que hospeda este material:

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

Portanto, em uma conclusão: os objetos são mais lentos mesmo no PHP 5.2. Não use objetos a menos que você realmente precise de seus recursos opcionais.

Quazzle
fonte
7
do usuário levans stackoverflow.com/users/1473035/levans : Eu executei isso com 5.3.8 e os objetos eram mais lentos, 0,51839280128479 para matrizes vs 0,85355806350708 para objetos. Também o executei em 5.4.13 e obtive os resultados opostos, provavelmente devido às otimizações de classe feitas em 5.4, 0,6256799697876 para matrizes vs 0,43650078773499. Portanto, parece que a situação mudou e os objetos são agora o caminho a seguir.
Jean-Bernard Pellerin
1
Boa resposta, acabei de testar no XAMPP (Apache) e obtive os resultados abaixo: arrays: 0,5174868106842 Array ([aaa] => aaa [bbb] => bbb [ccc] => aaabbb) obj: 0.72189617156982 stdClass Object ([aaa] => aaa [bbb] => bbb [ccc] => aaabbb) phpversion 5.4.19
ilhnctn
1
Também executei em 5.4.13, mas consegui o oposto de Jean-Bernard Pellerin: Arrays: 0,5020840167999 Objetos: 1,0378720760345 Então, eu não iria me comprometer com objetos ainda.
simontemplar
Fiz algumas mudanças no código e Class é mais rápido do que Arrays para php 5.4 (5.4.16 32bits Windows). Coloquei uma nova resposta que explica o motivo.
magallanes
PHP 5.5.11 Resultados: Arrays: 0,17430, Objetos: 0,24183
Lex de
4

script de magallanes @ PHP 7.3.5

  • SomeClass Object é mais rápido e mais leve.
  • Array Velocidade de 1,32x . 2.70x memória.
  • stdClass Object Velocidade de 1,65x . Memória 2.94x .

Saída bruta:

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
)
Qcho
fonte
3

Eu uso o código de magallanes sob 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
)

E o usuário php 7.1.3:

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
)                      
cariótico
fonte
1
E não se esqueça de que stdClass pode usar uma chave numérica de string real. ['1' => 1] será armazenado como [1 => 1], mas podemos usar $a=new stdClass(); $a->{1} = 1; $b=(array)$a;get real ['1' => 1].
chariothy
2
Concluindo, os arrays são 18% mais rápidos, mas consomem 2,7x mais memória.
jchook
3

Para quem ainda está interessado nesta questão :) Eu executei o código Quazzle no PHP 7.1 Ubuntu x64 e obtive esta resposta:

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
)

Conclusão

Array leva 4 (!) A memória do que o objeto de classe.
Objeto de classe um pouco mais rápido.
stdClass ainda mal © magallanes :)

ShadowMad
fonte
2

Você não nos mostrou o código de como $object->valuefunciona, pois pode ser que o backend seja um array, caso em que, teoricamente, usar um array seria mais rápido, pois envolve uma chamada de função a menos. O custo de fazer a pesquisa provavelmente será enorme em comparação com a chamada de função. Se for uma variável, haverá muito pouca diferença, pois os objetos e arrays no PHP têm uma implementação muito semelhante.

Se você estiver procurando por otimizações, precisará definir o perfil para verificar onde a maior parte do tempo está sendo usada. Suspeito que a mudança de objetos em matrizes não fará grande diferença.

Yacoby
fonte
Presumi que o valor seria uma variável pública, portanto, definitivamente O (1), enquanto a pesquisa de hash pode não ser.
Filip Ekberg
2

Vejo que este é um post meio antigo, então pensei em atualizá-lo. aqui estão meus códigos e estatísticas, feitos no Zend CE 5.3.21. Tentei testar a coisa toda, armazenando informações e puxando-as de volta.

V1: leva 0,83 s

for ($i=1; $i<1000000; $i++) {
  $a = get_one();
  $b = $a[0];
  $b = $a[1];
}

function get_one() {
  return array(1,1);
}

V2: leva 3,05 segundos

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: leva 1,98 s (observe que o construtor melhora o desempenho)

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;
  }
}
Nir
fonte
2

Bem, eu fiquei curioso hoje com base no benchmark @magallanes, então o expandi um pouco. Eu aumentei alguns dos loops for para realmente destacar as lacunas entre as coisas. Ele está sendo executado no Apache 2.4, mod_php e PHP 7.2.

Aqui está uma tabela de resumo para facilitar os resultados:

+---------------------------+---------+-----------------+
|           Test            | Memory  |      Time       |
+---------------------------+---------+-----------------+
| Array                     | 2305848 | 9.5637300014496 |
| stdClass                  | 2505824 | 11.212271928787 |
| SomeClass                 |  963640 | 11.558017015457 | <-- *
| AnotherClass              | 2563136 | 10.872401237488 |
| SetterClass               |  905848 | 59.879059791565 |
| SetterClassDefineReturn   |  905792 | 60.484427213669 |
| SetterClassSetFromParam   |  745792 | 62.783381223679 |
| SetterClassSetKeyAndParam |  745824 | 72.155715942383 |
+---------------------------+---------+-----------------+
* - Winner winner chicken dinner

Abaixo está o script modificado. Eu queria testar propriedades de configuração com métodos e tipos de definição. Fiquei muito surpreso ao descobrir que o uso de métodos setter adiciona um acerto significativo ao código. Concedido, este é um teste de desempenho muito específico, onde muitos aplicativos nem chegam a isso. Mas se você tem um site que lida com 1000 / reqs / segundo com 1000 classes que são usadas com 1000 de objetos, você pode ver como isso pode afetar o desempenho.

<?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<5000; $i++) {
    $z = new SomeClass();
    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 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);

E aqui estão os resultados:

Time Taken (seconds): 11.558017015457

Memory: 963640

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
)

n0nag0n
fonte
1

Você sempre pode verificar o código-fonte do PHP para recursos de micro-desempenho como esse.

Mas à primeira vista, nada de fazer ['valor'] não será mais rápido porque o PHP precisa fazer uma pesquisa sobre onde encontrar ['valor'], mesmo que uma pesquisa com hash deva ser O (1), isso não é garantido. Há mais sobrecarga quando você usa o índice de texto.

Se o objeto contiver apenas 1 variável que você precisa acessar, que é valor, haverá mais sobrecarga no uso de um objeto.

Filip Ekberg
fonte
E onde você acha que as propriedades são pesquisadas? Eles também estão em uma tabela hash ... (embora isso seja mais ou menos verdadeiro no tronco).
Artefacto
0

Se Arrays e Classs tiverem o mesmo desempenho, acho que usar objetos de classes predefinidas para armazenar / passar dados de negócios tornaria nosso programa mais lógico e o código mais legível.

Hoje, com ideias modernas como Eclipse, Netbean ... é muito conveniente saber quais informações um objeto (de classe predefinida) está carregando, mas os arrays não são assim

Ex: Com matriz

function registerCourse(array $student) {
    // Right here I don't know how a $student look like unless doing a print_r() or var_dump()
 ....
}

Com objeto

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
    ...
}
Trungnnh
fonte
Isso contradiz as outras respostas comprovadas e não tem provas. Portanto, esta é mais uma crença ideológica do que uma resposta real.
scones de
0

Para ser justo, depende do tipo de dados que você possui. Os resultados nas outras respostas são (mais ou menos) * corretos. Vou colar o código de teste na parte inferior para maior clareza.

O importante aqui é que você pode economizar uma boa quantidade de memória se usar um objeto predefinido, a compensação é o fato de que você precisa definir a estrutura exata.

Considere os seguintes resultados de teste:

static obj: 0.04223108291626
memory: 164920
object(staticSet)#1 (3) {
  ["aaa"]=>
  string(3) "aaa"
  ["bbb"]=>
  string(3) "bbb"
  ["ccc"]=>
  string(6) "aaabbb"
}
---------------------------------------
static obj with an additional prop: 0.042968988418579
memory: 524920
object(staticSet2)#1000 (3) {
  ["aaa"]=>
  string(3) "aaa"
  ["bbb"]=>
  string(3) "bbb"
  ["ddd"]=>
  string(6) "aaabbb"
}
---------------------------------------

Posso estar errado aqui, não pesquisei o código-fonte do PHP, mas acredito que, no que diz respeito ao PHP, tudo é um array. Um objeto predefinido é apenas um array bem definido. Uma nota interessante é que o tipo de valor não tem efeito ie. um valor de string '1' ocupará a mesma quantidade de memória que um valor booleano true.

Por quê? Bem, como eu disse antes, o PHP é arrays, então se você tem um objeto com uma função setter, o que (uma versão simplificada) o PHP faz é o seguinte:

$objects = ['objectName' => [
    'aaa' => '',
    'bbb' => '',
    'ccc' => '',
    'setValue:f' => function('name', 'value') { ... }
    ]
];

Cada vez que você executa, você faz uma pesquisa para a tecla de função que faz uma pesquisa para um nome de prop, mais qualquer validação de tipo de prop, etc. em segundo plano. A economia de memória em um objeto predefinido vem da definição de um array de um comprimento definido (de outra forma impossível em PHP) em vez de alocar um pedaço de memória.

Conclusão:

Objetos estáticos: Yey! Economizamos memória! Mas se você tentar adicionar algo fora da definição, ele ficará maior do que um stdClass.

['aaa'] into [['aaa'],['bbb']]

Arrays: se você escreve em PHP, é melhor amá-los, até mesmo uma string é um array de caracteres em PHP.

Objetos: objetos têm funcionalidade bacana, são uma maneira maravilhosa de manter seu código organizado, limpo e modular. Mas como todos sabemos "com grande poder ...".

Finalmente, meu código de teste e o '*'. as pessoas parecem esquecer que se você não limpar suas variáveis ​​enquanto o script está em execução, elas permanecerão na memória, embora não impactem o tempo de execução (muito), impactarão a medição da memória. Portanto, enquanto executa um perfil de memória, unset () é seu amigo.

<?php

error_reporting(E_ALL);
ini_set('display_errors',1);

$noOfObjects = 1000;
$noOfOperations = 1000;

class set {
    public function setKey($key, $value) {
        $this->{$key} = $value;
    }
    public function readKey($name) {
        return $this->{$name};
    }
}

class staticSet {
    public string $aaa;
    public string $bbb;
    public string $ccc;
}

class staticSet2 {
    public string $aaa;
    public string $bbb;
}

class staticSet3 {
    public bool $aaa;
    public bool $bbb;
    public bool $ccc;
}

$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = array(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'arrays: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new set(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->setKey('aaa','aaa');
        $z->setKey('bbb','bbb');
        $z->setKey('ccc',$z->readKey('aaa').$z->readKey('bbb'));
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'dynamic obj: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new staticSet(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->{'aaa'} = 'aaa';
        $z->{'bbb'} = 'bbb';
        $z->{'ccc'} = $z->{'aaa'}.$z->{'bbb'};
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'static obj: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new staticSet2(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->{'aaa'} = 'aaa';
        $z->{'bbb'} = 'bbb';
        $z->{'ddd'} = $z->{'aaa'}.$z->{'bbb'};
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'static obj with an additional prop: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime($noOfObjects);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new Ds\Map(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->put('aaa','aaa');
        $z->put('bbb','bbb');
        $z->put('ccc',$z->get('aaa').$z->get('bbb'));
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'Ds\Map: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new staticSet(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->{'aaa'} = '1';
        $z->{'bbb'} = '1';
        $z->{'ccc'} = ($z->{'aaa'} && $z->{'bbb'});
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'static obj with bool values: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new staticSet3(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->{'aaa'} = '1';
        $z->{'bbb'} = '1';
        $z->{'ccc'} = ($z->{'aaa'} && $z->{'bbb'});
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'static obj with defined bool values: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = array('aaa' => '','bbb' => '','ccc' => ''); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'predefined array: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;


echo 'phpversion '.phpversion().PHP_EOL;
Sonâmbulo
fonte