To pytanie jest tylko dla mnie, ponieważ zawsze lubię pisać zoptymalizowany kod, który może działać również na tanich, powolnych serwerach (lub serwerach z DUŻYM ruchem)
Rozejrzałem się i nie mogłem znaleźć odpowiedzi. Zastanawiałem się, co jest szybsze między tymi dwoma przykładami, pamiętając, że klucze tablicy w moim przypadku nie są ważne (oczywiście pseudokod):
<?php
$a = array();
while($new_val = 'get over 100k email addresses already lowercased'){
if(!in_array($new_val, $a){
$a[] = $new_val;
//do other stuff
}
}
?>
<?php
$a = array();
while($new_val = 'get over 100k email addresses already lowercased'){
if(!isset($a[$new_val]){
$a[$new_val] = true;
//do other stuff
}
}
?>
Ponieważ nie chodzi o kolizję tablic, to dodam, że jeśli boisz się kolizji wstawek $a[$new_value]
to możesz użyć $a[md5($new_value)]
. nadal może powodować kolizje, ale eliminuje możliwy atak DoS podczas odczytu z pliku dostarczonego przez użytkownika ( http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html )
php
performance
micro-optimization
Fabrizio
źródło
źródło
Odpowiedzi:
Dotychczasowe odpowiedzi są trafne. Używanie
isset
w tym przypadku jest szybsze, ponieważin_array
musi sprawdzać każdą wartość, dopóki nie znajdzie dopasowania.in_array
wbudowanej.Można to zademonstrować, używając tablicy z wartościami (10 000 w poniższym teście), wymuszając
in_array
dalsze wyszukiwanie.Opiera się to na benchmarku Jasona, wypełniając kilka losowych wartości i od czasu do czasu znajdując wartość, która istnieje w tablicy. Wszystkie losowe, więc uważaj, że czasy będą się zmieniać.
źródło
isset()
jest szybszy.Chociaż powinno to być oczywiste,
isset()
testuje tylko jedną wartość. Natomiastin_array()
będzie iterować po całej tablicy, testując wartość każdego elementu.Szorstkie testy porównawcze są dość łatwe w użyciu
microtime()
.Wyniki:
Uwaga: wyniki były podobne, niezależnie od tego, czy istniały, czy nie.
Kod:
Dodatkowe zasoby
Zachęcam również do obejrzenia:
źródło
microtime()
innych narzędzi. Niezwykle cenne.in_array
funkcji w porównaniu z użyciem funkcjiisset
wbudowanej. Byłoby to lepsze w przypadku tablicy zawierającej zestaw losowych kluczy i od czasu do czasu wyszukującej istniejący klucz / wartość.while
iforeach
że na każdym odświeżeniu ja dostawałem różne „zwycięzców”. zawsze zależy od zbyt wielu zmiennych serwera, a najlepiej jest iterować bardzo dużą liczbę razy w różnych momentach i uzyskać ten, który wygrywa częściej, lub po prostu wiedzieć, co dzieje się w tle i wiedzieć, że będzie to ostateczny zwycięzca nie ważne coisset()
tego, co sprawia, że myślisz, że przekazanie jej większej tablicy przyspieszyło ?Używanie
isset()
korzysta z szybszego wyszukiwania, ponieważ używa tablicy skrótów , unikając potrzebyO(n)
wyszukiwania.Klucz jest najpierw szyfrowany za pomocą funkcji skrótu djb w celu określenia zasobnika podobnie zaszyfrowanych kluczy
O(1)
. Zasobnik jest następnie przeszukiwany iteracyjnie, aż dokładny klucz zostanie znaleziony wO(n)
.Z wyjątkiem jakichkolwiek celowych kolizji hash , to podejście zapewnia znacznie lepszą wydajność niż
in_array()
.Zwróć uwagę, że podczas używania
isset()
w pokazany sposób, przekazanie końcowych wartości do innej funkcji wymaga użyciaarray_keys()
do utworzenia nowej tablicy. Naruszenie pamięci może nastąpić poprzez przechowywanie danych zarówno w kluczach, jak i wartościach.Aktualizacja
Dobrym sposobem sprawdzenia, jak decyzje dotyczące projektu kodu wpływają na wydajność środowiska uruchomieniowego, możesz sprawdzić skompilowaną wersję swojego skryptu:
echo isset($arr[123])
echo in_array(123, $arr)
Nie tylko
in_array()
używa stosunkowo nieefektywnegoO(n)
wyszukiwania, ale również musi być wywoływane jako funkcja (DO_FCALL
), podczas gdyisset()
używa do tego pojedynczego opcode (ZEND_ISSET_ISEMPTY_DIM_OBJ
).źródło
Drugi byłby szybszy, ponieważ szuka tylko tego konkretnego klucza tablicy i nie musi iterować po całej tablicy, dopóki nie zostanie znaleziony (sprawdzi każdy element tablicy, jeśli nie zostanie znaleziony)
źródło
isset()
jeśli nie została znaleziona?