Я могу предложить небольшое представление о трассировке источника C для in_array
.
Оказывается, при сравнении целых чисел , путь для достижения фактической проверки на равенство в нестрогом режиме включает меньше операций, чем в строгом режиме.
Строгий режим
В случае, если флаг strict
для in_array
имеет значение true, происходит следующее:
Мы вызываем fast_is_identical_function
для каждого элемента в массиве
fast_is_identical_function
первый
проверяет, что типы каждого операнда различны (Z_TYPE_P(op1) != Z_TYPE_P(op2)
) в надежде на возможность вернуть false
рано; это сравнение # 1 .
Если типы совпадают (они есть в вашем тестовом примере), тогда мы тестируем (Z_TYPE_P(op1) <= IS_TRUE
; Я понятия не имею, что это делает, но это сравнение # 2 .
После того, как оба сравнения оцениваются как false
, , мы переходим к zend_is_identical
, нашему первому вызову функции.
zend_is_identical
начинается с снова тестирование Z_TYPE_P(op1) != Z_TYPE_P(op2)
, еще одна попытка рано провалиться. Это сравнение # 3 .
Если типы совпадают, мы можем спуститься через оператор switch (Z_TYPE_P(op1))
, сравнение # 4
Наконец мы достигаем сравнения Z_LVAL_P(op1) == Z_LVAL_P(op2)
, которое фактически проверяет равенство двух значений, сравнение # 5 .
Всего, чтобы проверить, равен ли каждый элемент массива искомому значению, есть 5 сравнений и 1 вызов функции.
Нестрогий режим
Для сравнения, строгий поток для целых чисел (на самом деле LONG
s) намного проще, как показано ниже:
Вместо fast_is_identical_function
, вместо этого мы используем fast_equal_check_function
для каждого элемента в массиве.
Метод fast_equal_check_function
запускает гораздо более сложный процесс сравнения двух значений со всеми видами логики приведения типов. Однако сам тест first , который он действительно выполняет, оптимизирован для целых чисел следующим образом:
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
return Z_LVAL_P(op1) == Z_LVAL_P(op2);
Мы видим, что это ...
- немедленно проверяет, является ли тип
op1
LONG
, то есть
- немедленно проверяет, является ли тип
op2
LONG
, то есть
- немедленно возвращает результат
Z_LVAL_P(op1) == Z_LVAL_P(op2)
Всего 3 простых сравнения на равенство и 0 вызовов функций для нестрогого случая, против не менее 5 сравнений и 1 переход для строгого случая.
Это, похоже, тот случай, когда попытка ранней оптимизации делает строгую проверку медленнее (путем многократного тестирования типов операндов в надежде, что мы сможем быстрее найти неравенство), чем конкретный нестрогий случай сравнивая два целых числа.