Hände weg von array_key_exists ()

Post von realloc | Einsortiert in Code, Meckerecke am 4. Oktober 2006 | 2 Kommentare

Bei steigender Komplexität der Anwendung soll die Geschwindigkeit in der Ausführung natürlich nicht auf der Strecke bleiben. Man kämpft um jede 10tel Sekunde . Datenbank-Statements werden optimiert, es wird nach der Anzahl der Kontextwechsel zwischen der DB und der Anwendung gesucht, das Design der ganzen Architekur überarbeitet. Manchmal aber kann man ganz klein beginnen und unglaubliche Ergebnisse erzielen.

Schon mal array_key_exists () ausprobiert? Zugegeben, es fällt anfangs garnicht auf. Aber werden die Arrays der SQL-Results größer, kann der Effekt, den man erzielt, wirklich ärgerlich sein. Ich möchte garnicht darüber nachdenken, wie diese Funktion implementiert wurde. Das sie existiert, finde ich schon schlimm genug. Was spricht eigentlich dagegen anstelle von array_key_exists () eher isset () einzusetzen? Auf der Website des php.net kann man dazu folgendes lesen:

isset () gibt nicht TRUE zurück für Schlüssel eines Arrays, die zu einem NULL-Wert gehören, array_key_existis() tut dies hingegen.

Wow! Das erklärt alles! Das Ding kann von Items eines Arrays, die NULL sind, sagen, daß sie existieren. Wozu braucht man das? Ich habe das ehrlich nie gebraucht und für einen Vorteil, den ich nicht erkennen kann, soll ich mit 120% mehr Ausführungszeit im Durchschnitt bezahlen. Das ist übrigens ein Wert, den ich mit einem kleinen Test erzielt habe und der arbeitet nur mit Arrays, deren Schlüssel aus Integer-Werten bestehen:

function getmicrotime () {
   list ($usec, $sec) = explode(" ", microtime());
   return ((float)$usec + (float)$sec);
}

define ("TESTARRAY_MIN", 1);
define ("TESTARRAY_MAX", 10000);
define ("WINNERARRAY_MAX", 10);
define ("MEASURE_MAX", 10);

srand ((double) microtime() * 1000000);
$j = rand ();
$testArr = array ();
for ($i = TESTARRAY_MIN; $i <= TESTARRAY_MAX; $i++) {
    $testArr[$i] = $i * $j;
}

srand ((double) microtime () * 1000000);
$winnerArr = array ();
for ($i = 0; $i < WINNERARRAY_MAX; $i++) {
    $winnerArr[] = rand (TESTARRAY_MIN, TESTARRAY_MAX);
}

$measureArr = array ();
$trash = 0;
for ($i = 0; $i < MEASURE_MAX; $i++) {
    $starttime = getmicrotime ();
    foreach ($winnerArr as $key) {
        if (array_key_exists ($key, $testArr)) {
            $trash = $testArr[$key];
        }
    }
    $measureArr[$i][0] = getmicrotime() - $starttime;

    $starttime = getmicrotime ();
    foreach ($winnerArr as $key) {
        if (isset ($testArr[$key])) {
            $trash = $testArr[$key];
        }
    }
    $measureArr[$i][1] = getmicrotime() - $starttime;
}

$average = 0;
foreach ($measureArr as $value) {
    $average += $value[0] * 100.00 / $value[1];
}
printf ("%01.2f", ($average / MEASURE_MAX));

Have fun!

Möglicherweise interessiert Dich auch...

2 Antworten auf “Hände weg von array_key_exists ()”

  1. Thomas sagt:

    Quick and dirty… ja das ist “isset”
    Du hast schon recht Geschwindigkeit ist wichtig aber:
    1.) isset ist kein guter Stiel denn es ist keine Funktion sondern ein Sprachkonstrukt das als Funktion “getarn” ist.
    2.) isset prüft ob ein Wert vorhanden ist d.h. NULL als Eintarg im Array ist kein Wert => false; array_key_exists() prüft ob der Schlüssel vorhanden ist d.h. der Wert kan sein was er will!

    Also: array_key_exists() ist die saubere Lösung! …wenn man weiß was man tut und Geschwindigkeit braucht (z.B. in einer Schleife) dann kann man isset verwenden!

    Gruß Thomas

  2. realloc sagt:

    Ich spreche da aus Erfahrung. Bei einer Optimierung einer Backendlösung, die elend langsam lief, war nicht etwa die Datenbank, sondern die Verwendung von array_key_exists() das Problem. In den seltensten Fällen muss man meiner Meinung nach wissen, ob da irgendwo ein Item mit dem Wert NULL ist.

Einen Kommentar schreiben