A função count () do PHP é O (1) ou O (n) para arrays?

96

Será que count()realmente contam os todos os elementos de uma matriz PHP, ou se este valor em cache em algum lugar e só fica recuperados?

Dexter
fonte
6
Por que não testar? é simples fazer um loop que adiciona elementos a um array e conta cada vez e faz algum tempo.
Marc B
3
Dê uma olhada nesta pergunta: stackoverflow.com/questions/2473989/…
The Pixel Developer
Palavras-chave do Google - esta questão também pode ser formulada como: PHP count () itera sobre array ou recupera count da propriedade array?
jave.web

Respostas:

136

Bem, podemos olhar a fonte:

/ext/standard/array.c

PHP_FUNCTION(count)chamadas php_count_recursive(), que por sua vez chamam zend_hash_num_elements()uma matriz não recursiva, que é implementada desta forma:

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

    return ht->nNumOfElements;
}

Então você pode ver, é O(1)para $mode = COUNT_NORMAL.

Vladislav Rastrusny
fonte
6
O que IS_CONSISTENT(ht)fazer?
Mateus
1
Obrigado! Eu não tinha certeza de onde deveria procurar no código-fonte ou onde obter o código-fonte (sem ter que retirá-lo de um repositório).
Dexter
3
@Matt Está verificando se a estrutura hash é válida, como posso ver. É definido em zend_hash.c e é O (1) também.
Vladislav Rastrusny
10
Não posso deixar de votar em alguém que procura a resposta no código-fonte do PHP :)
Lamy
1
@Matt IS_CONSISTENT () é apenas uma verificação de sanidade na matriz github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
John Carter
7

No PHP 5+, o comprimento é armazenado no array para que a contagem não seja feita todas as vezes.

EDIT: Você também pode achar esta análise interessante: Desempenho de contagem de PHP . Embora o comprimento do array seja mantido pelo array, ainda parece que é mais rápido mantê-lo se você for chamar count()muitas vezes.

Jberg
fonte
Acho que você pode estar certo de que a mudança foi feita a partir do PHP 5. No entanto, ainda não encontrei a prova de que o PHP 4 era O (n) para count (); Eu apenas vejo comentários anedóticos. Você consegue encontrar a prova (ou seja, a implementação de count () para PHP 4)? Obrigado,
Kristopher Windsor
3

PHP armazena o tamanho de um array internamente, mas você ainda está fazendo uma chamada de função quando é mais lenta do que não fazer uma, então você vai querer armazenar o resultado em uma variável se estiver fazendo algo como usá-lo em um ciclo:

Por exemplo,

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

Além disso, você nem sempre pode ter certeza de que countestá sendo chamado em um array. Se for chamado em um objeto que o implementa, Countablepor exemplo, o countmétodo desse objeto será chamado.

mfonda
fonte
Como acompanhamento, você pode querer ler josephscott.org/archives/2010/01/php-count-performance Ele basicamente detalha como obter o comprimento do array é o (1) e o impacto das chamadas de função repetidas.
TheClair
1
Fazer uma chamada de função é sempre mais lento do que não fazer uma? Eu não ficaria surpreso se o intérprete tivesse otimização embutida.
corsiKa
1
the count method of that object will be called, você pode explicar isso um pouco
Steel Brain
1
@SteelBrain se uma classe implementa a Countableinterface, então chamar count($object)é a mesma coisa que chamar $object->count(). Consulte 3v4l.org/oYSSC por exemplo.
mfonda
you're still making a function call when which is slower than not making oneEsta afirmação pode estar errada. Se você estiver fazendo o percurso manual, isso é O(n)operação. Mas se você quiser apenas recuperar um valor pré-calculado, a operação é O(1).
Jamshad Ahmad