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

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

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

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

[Некоторая справочная информация на моем сайте: CSS вверху. JS внизу (Jquery, пользовательский интерфейс JQuery, купленные движки меню awm / menu.js, движок tabs js, video swfobject.js) Черные линии на втором изображении показывают, что инициируется для загрузки. Злой робот - мой питомец "ZAM". Он безвреден и часто счастливее.]


Загрузка водопада: хронологическая | http://webpagetest.org enter image description here


Параллельные домены, сгруппированные | http://webpagetest.org enter image description here


Сайт-Перф водопад | http://site -perf.com enter image description here


Pingdom Tools Waterfall | http://tools.pingdom.com

enter image description here


GTmetrix Waterfall | http://gtmetrix.com

enter image description here


Ответы [ 19 ]

61 голосов
/ 27 января 2011

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

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

В частности, самый актуальный jQueryи на библиотеки jQuery UI можно ссылаться по этим URL-адресам (см. этот пост , если вам интересно, почему я пропустил 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 UI по умолчанию также позволяют извлекать его CSS и изображения из Google CDN .

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

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

17 голосов
/ 31 января 2011

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

12 голосов
/ 09 февраля 2011

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

В отношении этого: «Условный запрос If-Modified-Since вернул весь контент без изменений.» и мои комментарии.

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

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

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

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

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

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

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

Редактировать: я не заметил вашего добавления в ваш пост.

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
6 голосов
/ 27 января 2011

Ух, сложно объяснить что-либо с помощью этого изображения ... Но здесь некоторые пытаются:

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

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

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

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

4 голосов
/ 24 февраля 2011

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

Все ваши последние измененные заголовки установлены в субботу, 01 января 2011 г., 12:00:00 по Гринвичу, которая выглядит слишком «круглой» для реальной даты генерации; -)

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

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

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

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

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

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

4 голосов
/ 27 января 2011

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

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

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

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

4 голосов
/ 07 февраля 2011

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

4 голосов
/ 27 января 2011

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

Эти тесты подскажут вам, что не так и что нужно изменить.

3 голосов
/ 05 марта 2011

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

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

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

...