Является ли file_exist () в PHP очень дорогой операцией? - PullRequest
16 голосов
/ 25 ноября 2008

Я добавляю аватары в движок форума, который я разрабатываю, и спорю, стоит ли делать что-то простое (изображение форума называется .png) и использовать PHP, чтобы проверить, существует ли файл перед его отображением, или сделайте что-нибудь более сложное (но не очень) и используйте поле базы данных, содержащее имя отображаемого изображения.

Я бы предпочел пойти лично с методом file_exists (), так как это дает мне простой способ вернуться к аватару по умолчанию, если текущий не существует (пока), и его легко реализовать код мудрый. Тем не менее, я беспокоюсь о производительности, так как она будет запускаться один раз для каждого пользователя, отображаемого для каждой загрузки страниц на страницах чтения форума. Поэтому я хотел бы знать, вызывает ли функция PHP file_exists () в PHP какие-либо серьезные замедления, которые могут привести к значительному снижению производительности в условиях высокого трафика?

Если нет, отлично. Если да, что вы думаете об альтернативах отслеживания загруженного пользователем изображения? Спасибо!

PS: Различия в коде, которые я вижу, заключаются в том, что версии для проверки файлов позволяют файлам разговаривать, в то время как форма базы данных верит, что база данных точна и не проверяет. (это просто URL, который, конечно, передается в браузер.)

Ответы [ 7 ]

12 голосов
/ 25 ноября 2008

Как и говорили другие авторы, PHP автоматически кеширует результат file_exists () для повышения производительности.

Однако, если вы уже читаете информацию о пользователе из базы данных, вы можете также хранить эту информацию там. Если пользователю разрешен только один аватар, вы можете просто сохранить один бит в столбце для «имеет аватар» (1/0), а затем иметь имя файла, совпадающее с идентификатором пользователя, и использовать что-то вроде SELECT CONCAT(IF(has_avatar, id, 'default'), '.png') AS avatar FROM users

Вы также можете сохранить фактическое изображение в базе данных как BLOB. Поместите его в свою собственную таблицу, а не присоединяйте в качестве столбца к пользовательской таблице. Преимущество этого заключается в том, что резервное копирование на вашем форуме очень просто - вы просто экспортируете базу данных.

8 голосов
/ 25 ноября 2008

В реальном тестировании производительности вы обнаружите, что file_exists очень быстро. Как и в php, когда один и тот же URL дважды "stat" и d, второй вызов просто извлекается из внутреннего кеша статистики php.

И это только в области запуска php. Даже между запусками файловая система / ОС будет стремиться агрессивно помещать файл в кэш файловой системы, и если файл достаточно мал, тест не только будет существовать из памяти, но и весь файл тоже.

Вот некоторые реальные данные, подтверждающие мою теорию:

Я только что провёл несколько тестов производительности утилит командной строки linux "find" и "xargs". В дальнейшем я выполнил тест на наличие файлов для 13000 файлов, по 100 раз каждый, менее чем за 30 секунд, так что в среднем это 43000 тестов в секунду, поэтому, конечно, в мелком масштабе, если вы сравниваете, скажем, время медленное требуется разделить 9 на 8, но в реальном сценарии вам придется делать это ужасно раз, чтобы увидеть заметную проблему с производительностью.

Если у вас есть 43 тысяча пользователей, одновременно обращающихся к вашей странице, в течение секунды, я думаю, у вас будут гораздо большие проблемы, чем время, необходимое для копирования статуса существования файл более или менее не хватает памяти в сценарии среднего случая.

8 голосов
/ 25 ноября 2008

Поскольку ваш веб-сервер уже будет выполнять много (эквивалентно) операций file_exists () в процессе показа вашей веб-страницы, еще один запуск вашего скрипта, вероятно, не окажет заметного влияния. Веб-сервер, вероятно, сделает по крайней мере:

  • по одному для каждого подкаталога веб-корня (для проверки существования и для символических ссылок)
  • один, чтобы проверить наличие файла .htaccess для каждого подкаталога веб-корня
  • один за существование вашего сценария

Это не учитывает больше из них, что PHP может сделать сам.

2 голосов
/ 26 ноября 2008

По крайней мере с PHP4 я обнаружил, что вызов file_exists определенно убивал наше приложение - оно было сделано очень глубоко в библиотеке, поэтому нам действительно пришлось использовать профилировщик, чтобы найти его. Удаление вызова увеличило вычисление некоторых страниц в десятки раз (вызов был сделан очень многократно).

Возможно, в PHP5 они кешируют file_exists, но по крайней мере в PHP4 это было не так.

Теперь, если вы не находитесь в цикле, очевидно, что file_exists не будет иметь большого значения.

0 голосов
/ 25 ноября 2008

Если производительность - ваше единственное соображение, то file_exists () будет намного дешевле, чем поиск в базе данных.

В конце концов, это всего лишь поиск в каталоге с использованием системных вызовов. После первого выполнения сценария большая часть соответствующего каталога будет кешироваться в хранилище, поэтому фактического ввода-вывода будет очень мало, а «file_exists ()» является настолько распространенной операцией, что она и основные системные вызовы оптимизирован для любой распространенной комбинации php / os.

Как отметил Иоанн II. Если дополнительные функциональные возможности и функции пользовательского интерфейса являются приоритетом, то база данных была бы подходящим вариантом.

0 голосов
/ 25 ноября 2008

В прошлом я сохранял метаданные изображения в базе данных (включая его имя), чтобы мы могли генерировать полезную статистику. Что еще более важно, хранение данных изображения (не самого файла, а только метаданных) способствует изменению . Что, если в будущем вам нужно «одобрить» изображение или вы хотите удалить его, не удаляя файл?

В соответствии с аватаром по умолчанию ... хорошо, если запись для этого пользователя не найдена, просто используйте запись по умолчанию.

В любом случае, file_exists () или db, это не должно быть узким местом для беспокойства. Однако одно решение гораздо более расширяемо.

0 голосов
/ 25 ноября 2008

file_exists () сам по себе не медленный. Реальная проблема заключается в том, как настроена ваша система и где узкие места в производительности. Помните, базы данных тоже должны хранить данные на диске, так что в любом случае вы можете столкнуться с дисковой активностью. С другой стороны, базы данных и файловые системы обычно имеют некоторую форму прозрачного кэширования для оптимизированного повторного доступа.

Вы можете легко пойти любым путем, так как есть вероятность, что ваше узкое место в производительности будет в другом месте. Единственное место, где я могу видеть, что это очевидный выбор, это если вы находитесь на каком-то перепроданном хостинге с перепроданностью, где существует масса конфликтов на диске, но, возможно, доступ к базе данных находится в отдельном кластере и быстрее (или наоборот).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...