array_merge este lent

Tocmai am întâmpinat o problemă cel puțin ciudată:

  1. Am un array multidimensional cu două-trei chei și câteva zeci de elemente;
  • acest array îl iterez cu un foreach iar fiecare element în trec printr-un array_merge, astfel încât să am niște valori default;
  • unele elemente nu au anumite chei, prin urmare făceam typecasting: array_merge( $default_values, (array) $iteratie['args'] )
  • bonus: am presupus că problema este la array_merge, prin urmare am încercat încă un foreach( (array) $iteratie['args'] ... ), fără succes (din contră: a crescut timpul de încărcare cu un sfert de secundă)

Ca să nu mai lungesc treaba: din cauza acelui typecasting mi se dubla timpul de încărcare. Rezolvarea?

if( isset( $iteratie['args'] ) && is_array( $iteratie['args'] ) ){
    $default_values = array_merge( $default_values, $iteratie['args'] );
}

Acum nu știu dacă e o problemă ce ține de Windows, Xampp, versiunile Apache/PHP sau doar faptul că se execută în WordPress, dar poate mai ajută pe cineva :wink:

Am o banuiala ca ai error_reporting setat pe E_ALL si display_errors pe 0, iar cand faci typecast unei variabile care nu exista, un E_NOTICE e generat si scris in error log (eventual si cu stack trace cu tot), chiar daca tie nu ti-l afiseaza (din cauza lui display_errors). Acum, de ce ar incetini cu asa mult scrierea in error log, nu am idee, dar e o directie in care te poti indrepta.

$a = array('nume' => 'Gigel');
$b = (array) $a['cheie_inexistenta'];

PHP Notice: Undefined index: cheie_inexistenta

1 Like

Într-adevăr, display_errors era 0 (chiar dacă aveam impresia că nu-i așa). Chiar setat corespunzător, tot există timpi mari de încărcare.

De asemenea, am observat că sunt timpi mari de încărcare cam de fiecare dată când există o eroare dar și când un test pică (testele rulează în mai puțin de o secundă; cum apare un test ce pică, este nevoie de 10-15 secunde).

Una peste alta, mă bucur că am rezolvat problema asta, căci îmi lua mult din elan :smiley:

Vezi ca si daca ai setat display_errors pe 1, si acum ti le afiseaza, nu inseamna ca nu le mai scrie si in error log. Iar daca zici ca asa se intampla la fiecare eroare, inseamna ca ceva e in neregula cu sistemul de error logging. Nu am mai facut dev pe Windows de multi ani si nu mai tin minte potentialele probleme, dar as incepe cu:

  1. Dimensiunea error-log-ului de Apache. L-as sterge ca sa fiu sigur ca incep cu unul gol.

  2. Daca nu cumva mai am si alte mecanisme care sunt implicate in procesul de error logging. Xdebug, etc. Le-as dezactiva si restart Apache, ca sa vad daca vreuna din ele influenta.

  3. M-as asigura ca elimin cauzele care tin efectiv de aplicatie testand cu un script mic de tot. L-am scris acum:

     error_reporting(E_ALL);
     ini_set('display_errors', 1);
    
     $time = microtime(true);
     $mem  = memory_get_usage();
    
     trigger_error('Whatever', E_USER_NOTICE);
    
     $time = microtime(true) - $time;
     $mem  = memory_get_usage() - $mem;
    
     $time = number_format($time, 2);
    
     echo "$time second(s)\n";
     echo "$mem bytes of memory used";

n-are nici o treaba. array_merge nu scuipa notificari daca nu se pupa cheile

Mai citeste o data codul. Nu la array_merge e problema, ci la faptul ca incearca sa acceseze $iteratie['args'], care cheie args nu exista in array-ul $iteratie.

daca te uiti atent vezi ca intai verifica daca exista cheia respectiva. dupa aia verifica daca-i array. isset nu scuipa norificari

Of, de ce deviezi o discutie fara sa citesti atent? Aia e solutia care i-a mers, nu aia initiala fara verificarea cu isset.

1 Like

ah, n-am fost atent la bucatica aia. my bad. oricum, solutia aia ar trebui sa-i rezolve problema. dar chiar si fara verificarile alea n-ar trebui sa dureze prea mult merge-ul (presupunand ca bucatica aia de cod nu-i intr-un loop)

Exemplul tău, în consolă (deci fără apache sau alți intermediari) zice așa:

php -f 1.php

Notice: Whatever in C:\work\projects\xxx\wp-content\plugins\catsone\1.php on line 9

Call Stack:
    0.0002     184456   1. {main}() C:\work\projects\xxx\wp-content\plugins\catsone\1.php:0
    0.0003     185000   2. trigger_error() C:\work\projects\xxx\wp-content\plugins\catsone\1.php:9

1.01 second(s)
376 bytes of memory used

Fără acel trigger_error am așa:

php -f 1.php
0.00 second(s)
80 bytes of memory used

Deci… Da, este o problemă. Prin urmare, am început să scot chestii din php.ini. Când am scos linia asta a redus timpul la 0 și a eliminat inclusiv problema cu phpunit menționată mai sus:

zend_extension = "C:\xampp\php\ext\php_xdebug.dll"

Voi căuta o altă versiune de xdebug, să vedem dacă rezolvă problema :blush:

Mulțumesc!


EDIT: versiunea asta merge… rezonabil: php_xdebug-2.2.6-5.5-vc11.dll. Ce înseamnă rezonabil? Codul de mai sus îmi trântește eroarea după 0.2 secunde iar testele pică în 2-3 secunde.

1 Like

pe dev ar fi normal sa stai cu e_all si error_reporting on. pe productie le scoti

Nu sunt de acord. Error reporting il lasi la fel si pe productie, schimbi doar sistemul de display si logging. Pe dev le scuipi direct, ca sa le vezi in timp ce muncesti, iar pe productie nu le mai afisezi userului, le scrii in log, iar cand trec de un anume nivel (de la warning in sus practic eu), le trimiti si pe mail.

5 Likes