Funktioniert PHP count () für Arrays O (1) oder O (n)?

96

Zählt count()wirklich alle Elemente eines PHP-Arrays oder wird dieser Wert irgendwo zwischengespeichert und nur abgerufen?

Dexter
quelle
6
Warum nicht testen? Es ist einfach genug, eine Schleife zu erstellen, die einem Array Elemente hinzufügt, jedes Mal zählt und ein Timing ausführt.
Marc B
3
Schauen Sie sich diese Frage an: stackoverflow.com/questions/2473989/…
The Pixel Developer
Google-Keywords - Diese Frage könnte auch wie folgt formuliert werden: Iteriert PHP count () über das Array oder ruft es die Anzahl aus der Array-Eigenschaft ab?
jave.web

Antworten:

136

Nun, wir können uns die Quelle ansehen:

/ext/standard/array.c

PHP_FUNCTION(count)Aufrufe php_count_recursive(), die wiederum ein zend_hash_num_elements()nicht rekursives Array erfordern, das folgendermaßen implementiert wird:

ZEND_API int zend_hash_num_elements(const HashTable *ht)
{
    IS_CONSISTENT(ht);

    return ht->nNumOfElements;
}

Sie sehen also, es ist O(1)für $mode = COUNT_NORMAL.

Vladislav Rastrusny
quelle
6
Was macht IS_CONSISTENT(ht)aber?
Matthew
1
Vielen Dank! Ich war mir nicht ganz sicher, wo in der Quelle ich suchen sollte oder wo ich die Quelle bekommen sollte (ohne sie aus einem Repository auschecken zu müssen).
Dexter
3
@Matt Es wird überprüft, ob die Hash-Struktur gültig ist, wie ich sehen kann. Es ist in zend_hash.c definiert und es ist auch O (1).
Vladislav Rastrusny
10
Ich kann es nicht verpassen, für jemanden zu stimmen, der nach der Antwort im PHP-Quellcode sucht :)
Lamy
1
@Matt IS_CONSISTENT () ist nur eine Überprüfung der Integrität des Arrays github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
John Carter
7

In PHP 5+ wird die Länge im Array gespeichert, sodass nicht jedes Mal gezählt wird.

BEARBEITEN: Diese Analyse könnte Sie auch interessieren: PHP Count Performance . Obwohl die Länge des Arrays vom Array beibehalten wird, scheint es immer noch schneller zu sein, daran festzuhalten, wenn Sie count()mehrmals aufrufen .

jberg
quelle
Ich denke, Sie haben vielleicht Recht, dass die Änderung ab PHP 5 vorgenommen wurde. Ich habe jedoch noch keinen Beweis dafür gefunden, dass PHP 4 für count () O (n) war. Ich sehe nur anekdotische Kommentare. Können Sie Beweise finden (dh die count () -Implementierung für PHP 4)? Vielen Dank,
Kristopher Windsor
3

PHP speichert die Größe eines Arrays intern, aber Sie führen immer noch einen Funktionsaufruf durch, wenn dieser langsamer ist als nicht. Daher möchten Sie das Ergebnis in einer Variablen speichern, wenn Sie es beispielsweise in einem verwenden Schleife:

Beispielsweise,

$cnt = count($array);
for ($i =0; $i < $cnt; $i++) {
   foo($array[$i]);
}

Außerdem können Sie nicht immer sicher sein, countdass ein Array aufgerufen wird. Wenn es für ein Objekt aufgerufen wird, das Countablebeispielsweise implementiert wird , wird die countMethode dieses Objekts aufgerufen.

mfonda
quelle
Als Follow-up möchten Sie vielleicht josephscott.org/archives/2010/01/php-count-performance lesen . Es beschreibt im Grunde, wie die Array-Länge o (1) ist und welche Auswirkungen die wiederholten Funktionsaufrufe haben.
TheClair
1
Ist ein Funktionsaufruf immer langsamer als ein Nichtaufruf? Es würde mich nicht wundern, wenn der Dolmetscher eine Inline-Optimierung hätte.
CorsiKa
1
the count method of that object will be called, können Sie dies bitte ein wenig erklären
Steel Brain
1
@SteelBrain Wenn eine Klasse die CountableSchnittstelle implementiert , count($object)ist das Aufrufen dasselbe wie das Aufrufen $object->count(). Siehe zum Beispiel 3v4l.org/oYSSC .
Mfonda
you're still making a function call when which is slower than not making oneDiese Aussage kann falsch sein. Wenn Sie manuell durchlaufen, ist dies eine O(n)Operation. Wenn Sie jedoch nur einen vorberechneten Wert abrufen möchten, lautet die Operation O(1).
Jamshad Ahmad