__DIR__ vs dirname( __FILE__ )
Вызов константы всегда должен быть быстрее, чем вызов функции, верно? В PHP есть два разных способа получить каталог, в котором в данный момент находится файл. __DIR__
— магическая константа, добавленная в PHP в версии 5.3. В официальной документации PHP конкретно указано: «Это эквивалентно dirname(__FILE__)
». Эквивалентность по возврату не обязательно означает эквивалентность по производительности, поэтому я решил проверить производительность обоих по паре переменных.
Методология тестирования
При выполнении большого количества тестов я обнаружил, что travis-ci может быть большим помощником. Вы можете определить матрицу тестов, которые хотите запустить, в качестве матрицы тестирования, а затем использовать результаты. Поэтому я настроил репо для своих тестов. Репозиторий состоит из четырех основных частей:
- Генератор файлов, который создает код, на котором я буду запускать тест производительности.
- Сценарий запуска теста, который запускает настоящие тесты.
- Файл travis.yml для определения матрицы моих тестов
- Файлы, используемые для фактического теста. Это не связано, там 400 000 файлов. Генератор показывает их.
Мой тест вызывает функцию, которую я ищу по 100 000. В одном прогоне все файлы находятся в одном каталоге, а в другом — по одному файлу в каждом каталоге. Я хотел исключить возможность того, что один каталог может повлиять на этот вызов.
Я провел этот тест на шести версиях PHP: 5.6.40, 7.0.33, 7.1.27, 7.2.15, 7.3.9 и 7.4-dev. Каждый тест выполнял 650 прогонов, и я посмотрел на __dir__
, так и dirname( __file__ )
по 130 000 000 раз каждый. Затем я взял время для каждого из этих запусков и посмотрел на этот максимальный (самый медленный) запуск для каждого и 95% времени (среднее между 618-м и 619-м самым медленным), чтобы исключить любые крайние случаи. В целом, результаты между максимумом и 95% аналогичны.
User
– это время, затрачиваемое ЦП на выполнение кода пользовательского режима (вне ядра) внутри процесс. Это только фактическое время ЦП, используемое при выполнении процесса. Другие процессы и время, которое процесс тратит заблокированным, не учитываются в этой цифре. Переполнение стека
__DIR__
vs имя_каталога (__FILE__)
Результаты тестовПроизводительность 95%
Сценарий | 5,6 | 7,0 | 7,1 | 7,2 | 7,3 | 7,4 |
каталог (1 папка) | 1,4 | 2,76 | 2,08 | 2,51 | 2,27 | 1,3615 |
каталог (много папок) | 1,38 | 2,29 | 2,55 | 2,3615 | 2,65 | 1,57 |
имя_директории( 1 папка) | 1,5815 | 2,27 | 2,7415 | 3,24 | 2,41 | 1,5215 |
имя_каталога (много папок) | 1,68 | 2,29 | 2. 0815 | 3,29 | 2,6815 | 1,87 |
В целом результаты показывают, что __dir__
обычно работает быстрее, но редко намного быстрее. Учтите, что при самом медленном запуске (с использованием PHP 7.2 и вызовом
для нескольких папок) каждый вызов занимал 0,0000329 секунд. Самый быстрый бег был на 2 стотысячных секунды быстрее. Это такая микрооптимизация, что, если не считать экстремальных масштабов, маловероятно, что вы когда-нибудь заметите разницу. При этом в большинстве версий PHP __DIR__
быстрее.
Итак:
__dir__
или имя_каталога
? В конце концов, производительность __DIR__
немного лучше, но, что более важно, я думаю, что он понятнее и легче читается. Итак, я в команде __dir__
, но производительность — это только бонус.
Если у вас есть другое мнение или вы считаете, что мою методологию тестирования можно улучшить, сообщите мне об этом в комментариях ниже.
#48082 (Заменить `dirname(__FILE__)` на `__DIR__` (улучшение производительности, масштабное исправление)) – WordPress Trac 055
В PHP 5. 3 добавлена магическая константа __DIR__
, которая совпадает с dirname(__FILE__)
. Поскольку имя_каталога()
является вызовом функции, каждый раз, когда мы используем имя_каталога(__FILE__) 9, это может иметь накладные расходы на вызов функции.0004 вместо
__DIR__
.
Теперь, когда нам требуется PHP 5.6 как минимальная версия, мы можем отказаться от вызовов
в пользу __DIR__
.
Приложен массивный патч, который заменяет все такие вызовы магической константой. Я проверил источник на предмет дальнейших вхождений, и теперь мы чисты.
Я понимаю, что анализировать такой большой патч сложно, но, надеюсь, мы сможем поместить этот набор изменений в один тикет, чтобы их было легко объединять/справляться.
Спасибо.
Приставки (5)
- 48082-1.patch (83,8 КБ) — добавлено ayeshrajans 4 года назад.
- 48082.