Кэшированные, сгенерированные PHP миниатюры загружаются медленно


Вопрос Часть A ▉ (100 bountys, награжден)
Главный вопрос был в том, как сделать этот сайт, загрузить быстрее. Сначала нам нужно было прочитать эти водопады. Спасибо всем за ваши предложения по анализу показаний водопада. Очевидно, что из различных графиков водопада, показанных здесь, является основным узким местом: созданные PHP эскизы. Загрузка jQuery без протокола из CDN, рекомендованная Дэвидом, получила мою награду, хотя и сделала мой сайт только на 3% быстрее в целом, и не отвечая на вопрос главное узкое место сайта. Время для разъяснения моего вопроса, и, еще одна щедрость:

Вопрос Часть B ▉ (100 bountys, награжден)
Новый фокус теперь должен был решить проблему, которую имели изображения 6 jpg, которые вызывают большую часть задержки загрузки. Эти 6 изображений являются PHP-генерируемые миниатюры, крошечные и только 3~5 КБ, но загрузка относительно очень медленно. Обратите внимание на "время до получения первого байта " на различных графиках. Проблема осталось нерешенным, но щедрость досталась Джеймсу, который исправил ошибку заголовка, что RedBot подчеркнутый:"условный запрос If-Modified-Since вернул полное содержимое без изменений.".

Вопрос Часть C ▉ (моя последняя награда: 250 очков)
К сожалению, после даже REdbot.org ошибка заголовка была исправлена, задержка, вызванная PHP-генерируемыми изображениями, осталась нетронутой. Что на Земле Эти крошечные крошечные миниатюры 3~5Kb думают? Все это информация заголовка может отправить ракету на Луну и обратно. Любые предложения по этому узкому месту очень ценятся и рассматриваются как возможный ответ, так как я застрял в этой узкой проблеме уже семь месяцев. Заранее благодарю.

[некоторая справочная информация на моем сайте: CSS находится в верхней части. JS в нижней части (на jQuery пользовательского интерфейса jQuery, купил меню с AWM меню/.JS двигатели, вкладки JS двигатель, видео swfobject.js)черные линии на втором изображении показывают, что инициирует загрузку. Злой робот - это мой питомец "зам". Он безвреден и часто счастливее.]


Загрузить Водопад: Хронологический | http://webpagetest.org


Параллельные Домены Сгруппированы | http://webpagetest.org


Сайт-Perf Водопад | http://site-perf.com


Водопад Инструментов Pingdom | http://tools.pingdom.com


Водопад GTmetrix | http://gtmetrix.com


19 178

19 ответов:

во-первых, использование этих нескольких доменов требует нескольких DNS-запросов. Тебе было бы лучше объединение многих из этих изображений в спрайт вместо того, чтобы распространять запросы.

во-вторых, когда я загружаю вашу страницу, Я вижу большую часть блокировки (~1.25 s) на всех.js. Я вижу, что начинается с (старой версии) jQuery. Вы должны ссылаться на это из Google CDN, а не только уменьшить время загрузки, а потенциально избежать HTTP-запроса для него полностью.

в частности, на эти URL-адреса можно ссылаться на самые последние библиотеки jQuery и jQuery UI (см. этот пост если вам интересно, почему я пропустил http:):

//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js

//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js

если вы используете одну из тем пользовательского интерфейса jQuery по умолчанию, вы также можете вытащите его CSS и изображения из Google CDN.

с оптимизированным хостингом jQuery вы также должны объединить awmlib2.js и tooltiplib.js в один файл.

если вы обратившись к этим вещам, вы должны увидеть значительное улучшение.

У меня была похожая проблема несколько дней назад, и я нашел головы.js. Это плагин Javascript, который позволяет загружать все файлы JS paralell. Надеюсь, это поможет.

Я далек от эксперта, но...

в связи с этим: "Условный запрос If-Modified-Since вернул полное содержимое без изменений." и мои комментарии.

код, используемый для создания эскизов, должен проверять следующее:

  1. есть ли кэшированная версия миниатюры.
  2. является ли кэшированная версия более новой, чем исходное изображение.

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

  1. есть ли заголовок HTTP_IF_MODIFIED_SINCE
  2. является ли время последнего изменения кэшированной версии таким же, как HTTP_IF_MODIFIED_SINCE

если любой из них является ложным, кэшированный эскиз должен быть возвращен.

Если оба из них истинны, то должен быть возвращен статус http 304. Я не уверен, если его требуется, но я также лично верните Cache-Control, Expires и Last-Modified заголовки вместе с 304.

что касается GZipping, мне сообщили, что нет необходимости в gzip-изображениях, поэтому игнорируйте эту часть моего комментария.

Edit: я не заметил вашего добавления к вашему сообщению.

session_cache_limiter('public');
header("Content-type: " . $this->_mime);
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 2419200) . " GMT");
// I'm sure Last-Modified should be a static value. not dynamic as you have it here.
header("Last-Modified: " . gmdate("D, d M Y H:i:s",time() - 404800000) . " GMT");

Я также уверен, что ваш код должен проверить заголовок HTTP_IF_MODIFIED_SINCE и реагировать на него. Просто установите эти заголовки и ваш .htaccess файл не будет предоставлять необходимые результат.

Я думаю, тебе нужно что-то вроде этого:

$date = 'D, d M Y H:i:s T'; // DATE_RFC850
$modified = filemtime($filename);
$expires = strtotime('1 year'); // 1 Year

header(sprintf('Cache-Control: %s, max-age=%s', 'public', $expires - time()));
header(sprintf('Expires: %s', date($date, $expires)));
header(sprintf('Last-Modified: %s', date($date, $modified)));
header(sprintf('Content-Type: %s', $mime));

if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
    if(strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified) {
        header('HTTP/1.1 304 Not Modified', true, 304);
        // Should have been an exit not a return. After sending the not modified http
        // code, the script should end and return no content.
        exit();
    }
}
// Render image data

Вау, трудно объяснить вещи, используя этот образ.. Но вот, некоторые пытается:

  • файлы 33-36 загружаются так поздно, потому что они динамически загружаются в swf, и swf (25) загружается сначала полностью, прежде чем он загружает любое дополнительное содержимое
  • файлы 20 и 21 являются может быть (Я не знаю, потому что я не знаю ваш код) библиотеки, которые загружаются всеми.js (11), но для выполнения 11 он ожидает загрузки всей страницы (и активов) (вы следует изменить это на domready)
  • файлы 22-32 загружаются этими двумя библиотеками, снова после того, как они полностью загружены

просто предположение, потому что этот вид анализа требует много A/B тестирования: ваш домен .ch кажется труднодоступным (длинные зеленые полосы до прибытия первого байта).

Это будет означать, что либо веб-сайт .ch плохо размещен, либо у вашего провайдера нет хорошего маршрута к ним.

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

на боковой ноте, есть этот классный инструмент cuzillion что может помочь вам сортируйте вещи в зависимости от вашего заказа загрузки ресурсов.

попробуйте запустить Y!Медленные тесты и тесты скорости страницы на вашем сайте / странице, а также следуйте инструкциям, чтобы разобраться в возможных узких местах производительности. Вы должны получать огромный прирост производительности, как только вы набрали больше очков в Y!Медленная или скорость страницы.

эти тесты расскажут вам, что не так и что нужно изменить.

Итак, ваш PHP-скрипт генерирует миниатюры при каждой загрузке страницы? Во-первых, если изображения, которые миниатюры не меняются так часто, не могли бы вы настроить кэш таким образом, что они не должны быть проанализированы каждый раз при загрузке страницы? Во-вторых, ваш PHP скрипт использует что-то вроде imagecopyresampled() для создания эскизов? Это нетривиальный пример downsample, и php-скрипт ничего не вернет, пока не будет сделано сокращение вещей. Используя imagecopymerged() вместо этого снизит качество изображение, но ускорить процесс. И насколько сильно вы сокращаетесь? Эти миниатюры 5% размер исходного изображения или 50%? Больший размер исходного изображения, вероятно, приводит к замедлению, так как PHP-скрипт должен получить исходное изображение в памяти, прежде чем он сможет сжать его и вывести меньший эскиз.

Я нашел URL вашего сайта и проверил отдельный файл jpg с главной страницы. Хотя время загрузки сейчас разумно (161 МС), оно ждет 126 мс, что слишком много.

ваши последние измененные заголовки все установлены в Sat, 01 Jan 2011 12: 00: 00 GMT, который выглядит слишком "круглым", чтобы быть реальной датой генерации ; -)

поскольку Cache-control является "public, max-age=14515200", произвольные последние измененные заголовки могут вызвать проблему после 168 дни.

в любом случае, это не реальная причина для задержки.

вы должны проверить, что делает ваш генератор миниатюр, когда миниатюра уже существует, и что может потреблять так много времени для проверки и доставки изображения.

вы можете установить xdebug чтобы профилировать скрипт и посмотреть, где узкие места.

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

Я понимаю, что вы не можете разместить свой платный генератор здесь, но я боюсь, что есть слишком много возможных проблем...

Если нет действительно веской причины (обычно ее нет), ваши изображения не должны вызывать интерпретатор PHP.

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

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

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

PHP блокирует данные сеанса для каждого запущенного скрипта с момента начала обработки сеанса до момента запуска скрипта заканчивается, или когда session_write_close() называется. Это эффективно сериализует вещи. Проверьте страницу PHP на сеансах, особенно комментарии, такие как этот.

Это просто дикая догадка, так как я не смотрел на ваш код, но я подозреваю, что сеансы могут играть здесь роль, следующее из ручного ввода PHP на session_write_close():

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

я закодировал функцию обслуживания составного файла и у меня была такая же проблема. При обслуживании большого файла I не удалось заставить работать составную функциональность, и я не мог открыть другую страницу, пока загрузка не будет завершена. вызов session_write_close() основные обе мои проблемы.

вы пробовали заменить php генерируемые ногти на обычные изображения, чтобы увидеть, если есть какая-либо разница ? Проблема может быть вокруг - ошибка в вашем php-коде, приводящая к регенерации миниатюры при каждом вызове сервера - задержка в вашем коде (sleep ()?) связанный с проблемой часов - проблема с жестким диском вызывает очень плохое состояние гонки, так как все миниатюры загружаются/генерируются одновременно.

Я думаю, вместо того, чтобы использовать это эскиз-генератор скрипта вы должны дать TinySRC попытка быстрого быстрого и облачного создания миниатюр. Она имеет очень простой и легкий в использовании API, вы можете использовать как:-

http://i.tinysrc.mobi/ [высота]/[ширина] /http://domain.tld / path_to_img.jpg

[ширина] (опционально):- Это ширина в пикселях (которая переопределяет адаптивную- или семейный размер). Если он имеет префикс ‘ - ’ или 'x', он будет вычитаться из определенного размера или уменьшаться до процента.

[высота] (опционально):- Это высота в пикселях, если ширина также присутствует. Он также переопределяет адаптивный или семейный размер и может иметь префикс ‘-’ или ‘x’.

вы можете проверить резюме API здесь


часто задаваемые вопросы

что стоит tinySrc я?

ничего.

когда я могу начать использовать tinySrc?

сейчас.

насколько надежен сервис?

мы не даем никаких гарантий о службе tinySrc. Однако он работает на основная, распределенная облачная инфраструктура, поэтому он обеспечивает высокую доступность по всему миру. Этого должно быть достаточно для всех ваших нужд.

как быстро это?

tinySrc кэширует измененные изображения в памяти и в нашем хранилище данных в течение 24 часов, и он не будет получать исходное изображение каждый раз. Это делает услуги молниеносная С точки зрения пользователя. (И уменьшает нагрузку на сервер в качестве приятного побочного эффекта.)


Удачи. Просто предложение, так как u не показывает нам код: p

поскольку некоторые браузеры загружают только 2 загрузки parallels на домен, не могли бы вы добавить дополнительные домены в осколок запросы более двух-трех различных имен хостов. например: 1.imagecdn.com 2.imagecdn.com

прежде всего, вам нужно справиться If-Modified-Since запросы и такие соответственно, как сказал Джеймс. Эта ошибка гласит:"Когда я спрашиваю ваш сервер, если это изображение изменяется с последнего раза, он отправляет все изображение вместо простого Да/нет".

время между соединением и первым байтом-это, как правило, время выполнения вашего PHP-скрипта. Очевидно, что что-то происходит, когда скрипт начинает выполняться.

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

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

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

вы пытались настроить несколько поддоменов под веб-сервер NGINX специально для статичных данных, таких как изображения и таблицы стилей? Что-то полезное уже можно найти в этой теме.

Что касается отложенных эскизов, попробуйте позвонить в flush () сразу после последнего звонка header () в сценарии создания миниатюр. После этого восстановите свой график водопада и посмотрите, есть ли задержка теперь на теле вместо заголовков. Если это так, вам нужно долго смотреть на логику, которая генерирует и / или выводит данные изображения.

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

большая часть медленной проблемы заключается в том, что ваш TTFB (время до первого байта) слишком высок. Это трудно решить, не знакомясь с вашими файлами конфигурации сервера, кодом и базовым оборудованием, но я вижу, что это безудержно по каждому запросу. У вас слишком много зеленых полос (плохо) и очень мало синих полос (хорошо). Возможно, вы захотите немного прекратить оптимизацию интерфейса, поскольку я считаю, что вы многое сделали в этой области. Несмотря на пословицу, что "80%-90% времени отклика конечного пользователя провел на фронтенде", Я считаю, что ваш происходит в бэкэнде.

TTFB это бэкэнд-материал, серверный материал, предварительная обработка перед выводом и рукопожатием.

время выполнения кода, чтобы найти медленные вещи, такие как медленные запросы к базе данных, время ввода и выхода функций/методов для поиска медленных функций. Если вы используете php, попробуйте Firephp. Иногда это один или два медленных запроса, выполняемых во время запуска или инициализации, как вытягивание информация о сеансе или проверка подлинности, а что нет. Оптимизация запросов может привести к некоторому хорошему выигрышу perf. Иногда код запускается с помощью php prepend или spl autoload, поэтому они работают на всем. В других случаях это может быть mal настроен apache conf и настройки, что экономит день.

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

вы можете попробовать предварительную выборку DNS для борьбы со многими доменами и ресурсами, http://html5boilerplate.com/docs/DNS-Prefetching/

является ли сервер вашим собственным хорошим / приличным сервером? Иногда лучший сервер может решить много проблем. Я поклонник 'аппаратное обеспечение дешево, программисты дорого' менталитет, если у вас есть шанс и деньги обновить сервер. И / или использовать CDN как maxcdn или cloudflare или аналогичные.

Удачи!

(p. s. Я не работаю ни на кого из указанные компании. Также ссылка cloudflare выше будет утверждать, что TTFB не так уж и важен, я бросил это туда, чтобы вы могли получить еще один дубль.)

к сожалению, вы предоставили мало данных. И у вас уже есть несколько хороших предложений.

Как вы обслуживаете эти изображения ? Если вы транслируете их через PHP, вы делаете очень плохую вещь, даже если они уже сгенерированы.

НИКОГДА НЕ ПОТОК ИЗОБРАЖЕНИЙ С PHP. Это замедлит ваш сервер, независимо от того, как вы его используете.

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

это исправит сеанс php, браузер-прокси, кэширование, ETAGS, все сразу.

WP-Supercache использует эту стратегию, если она правильно настроена.

Я написал это некоторое время назад ( http://code.google.com/p/cache-on-request/source/detail?r=8 ), последний ревизии сломаны, но я думаю, что 8 или менее должны работать, и вы можете захватить их .htaccess, как пример, просто чтобы проверить как все работает (хотя есть лучшие способы, чтобы настроить .htaccess, чем так, как я привык).

Я описал эту стратегию в этом блоге ( http://www.stefanoforenza.com/need-for-cache/ ). Это, вероятно, плохо написано, но это может помочь прояснить ситуацию.

Читать далее: http://meta.wikimedia.org/wiki/404_handler_caching