userxp
Администратор
   
Репутация: +400/-6
Offline
Пол: 
Сообщений: 3227
Злой и ужасный бармалей
|
 |
« : 07.03.2007, 01:28:01 » |
|
Сегодня запостили на форуме. Original version (>>> ссылка<<<): Hi, all!
Recently I've rewritten a pretty large site on Joomla (it has about 200 online users all the time, as Joomla backend stats shows, >17000 content items etc.) and noticed that the page generation time started to grow ftom 0.101 secs to 0.5 after the first day, 0.7 - 1 next day...). Not very good, right? First of all I went to the MySQL console at the time of high loads and... voila - there is a `opensef_sef` MySQL query present almost constantly.
Guys, if somebody can explain me why do you fetch into the memory almost all records in sef.php [Line #173]:if ($sefSite->id == null) $sefSite->id = -1; $query = "SELECT * FROM #__opensef_sef WHERE published = '1'" . "\nAND valid = '1'" . "\nAND (direction IS NULL OR direction = '' OR direction = 'o')" . "\nAND (site_id IS NULL " . ($sefSite->id ? ' OR site_id = ' . $sefSite->id : '') . ')' . "\nORDER BY site_id DESC, published DESC, valid DESC, LENGTH(direction) DESC"; $database->setQuery( $query ); if ($database->loadResult()) { $opensef_aliases = $database->loadObjectList(); } A quick fix is to replace the query with this one:if ($sefSite->id == null) $sefSite->id = -1; $query = "SELECT * FROM #__opensef_sef WHERE published = '1'" . "\nAND valid = '1'" . "\nAND (direction IS NULL OR direction = '' OR direction = 'o')" . "\nAND (site_id IS NULL " . ($sefSite->id ? ' OR site_id = ' . $sefSite->id : '') . ')' . "\nAND (external='{$_SERVER['REQUEST_URI']}'" . "\nORDER BY site_id DESC, published DESC, valid DESC, LENGTH(direction) DESC"; $database->setQuery( $query ); if ($database->loadResult()) { $opensef_aliases = $database->loadObjectList(); } Hurray! It works as a charm. Page generation time is now 0.07 seconds. Hope this will help somebody else. Thanks.Надо проверять
|
|
|
|
|
Записан
|
|
|
|
| |
|
alfim
Гость
|
 |
« Ответ #1 : 11.03.2007, 02:46:19 » |
|
Приветствую! userxp попросил меня отписать здесь о возможных исправлениях для OpenSEF RC5 SP2, так что все "спасибы" и претензии к нему :-) Итак, корень всех зол заключается в том, что OpenSEF почти всю табличку jos_opensef_sef вытягивает в массив в самом начале своей работы а после этого полным перебором (ужас!) искать там соответствие внутренняю УРЛ - внешняя УРЛ и наоборот. При этом, в случае, если сайт довольно обширный, и ЧПУ на нем много, массив получается просто огроменным. У меня на сайте с 17000 статей ПХП умирал с воем "не хватает памяти" при ограничении в 16Мб. Первый фикс был просто призван уменьшить количество записей, размещаемых в памяти. Но.. не тут-то было. Оказывается, OpenSEF этот же глобальный массив использует для всех-всех ссылок, котрые Джумла пытается привести "человеский вид" (перекрывается ф-я sefRelToAbs). Естесственно, простая фильтрация результатов запроса по REQUEST_URI нас уже не спасет. Пробуем следующий фикс: В файле administrator/components/com_sef/sef.class.php находим ф-ю lookupOutgoing, комментируем то, что там есть, и заменяем вот этим: function lookupOutgoing( $site_id, $url ) { // static method global $opensef_aliases, $database;
$returnaliases = array(); /* if ($site_id == null) $site_id = -1; if (count($opensef_aliases) > 0) { foreach($opensef_aliases as $aliases){ if ( $aliases->internal == $url ) { $returnaliases[] = $aliases; } } } */ if (!count($returnaliases)) { $query = "SELECT * FROM #__opensef_sef WHERE published = '1'" . "\nAND valid = '1'" . "\nAND (direction IS NULL OR direction = '' OR direction = 'o')" . "\nAND internal='$url'". "\nORDER BY site_id DESC, published DESC, valid DESC, LENGTH(direction) DESC limit 1";
$database->setQuery( $query ); if ($database->loadResult()) { $aliases = $database->loadObjectList(); foreach($aliases as $k=>$val) { $returnaliases[] = $val; } } }
if (is_array( $returnaliases ) && count( $returnaliases )) { $returnaliases = xclCastObjectList( $returnaliases, 'JosOpenSEFAlias' ); return $returnaliases[0]; } $null = null; return $null; }
Если хостер додумался включить кеширование запросов для MySQL - работать будет отлично, в противном случае, придется Вам всем подождать, пока я не проверю свою идею с кешированием результатов для lookupOutgoing или кто-то другой не придумает чего-то получше. Не забываем, что первый фикс тоже надо оставить (на самом деле, вообще надо убрать этот глобальный массив и запрос, который в него вытягивает данные, но я пока не знаю, как лучше всего это сделать). Спасибо. Жду отзывов.
|
|
|
|
|
Записан
|
|
|
|
|
murat
|
 |
« Ответ #2 : 11.03.2007, 19:04:57 » |
|
Тестировал на локальном сервере (denwer). После установки хака для файла sef.class.php число запросов (кеширование отключено) с 84 увеличилось до 123. После установки хака для sef.php число запросов стало 122, но появилось несколько notice.
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #3 : 11.03.2007, 22:56:45 » |
|
Приветствую! Суть изменений не в том, чтобы уменьшить количество запросов, а в том, чтобы уменьшить нагрузку на веб-сервер. Я полагаю, что на Вашем локальном сервере очень мало статей (content items), а следовательно, совсем немного записей в таблице jos_opensef_sef (раздел Components - OpenSEF - Manage Friendly URLs). В таком случае подход RC5 себя вполне оправдывает. Проблемы начинаются с увеличением количества записей в jos_opensef_sef. На 3х тысячах sef.php начинает заметно замедляться, и требовать неоправданно большого количества ОЗУ. 8Mb, выделяемых в php.ini по-умолчанию, уже становится недостаточно. Плюс к этому в lookupOutgoing применяется поиск полным перебором, а это просто недопустимо, учитывая то, что данная ф-я вызывается для всех ссылок, имеющихся на странице. Я предлагаю заменить полный перебор запросами к базе MySQL. В случае наличия индексов по полям internal и external таблицы jos_opensef_sef и большого (>5000) количества записей, это работает заметно быстрее, а памяти требует меньше. В файле components/com_sef/sef.php можно вообще закомментировать строки if ($sefSite->id == null) $sefSite->id = -1; $query = "SELECT * FROM #__opensef_sef WHERE published = '1'" . "\nAND valid = '1'" . "\nAND (direction IS NULL OR direction = '' OR direction = 'o')" . "\nAND (site_id IS NULL " . ($sefSite->id ? ' OR site_id = ' . $sefSite->id : '') . ')' . "\nORDER BY site_id DESC, published DESC, valid DESC, LENGTH(direction) DESC"; $database->setQuery( $query ); if ($database->loadResult()) { $opensef_aliases = $database->loadObjectList(); }
Или же применить хак, описанный в 1м посте. Все мои слова не голословны. Есть живой сайт (адрес не могу светить по причине договоренности с заказчиком, если шибко интересно - пишите в приват), на котором в час пик нагрузка была >1000 одновременных подключений. С оригинальным OpenSEF на выделенном сервере с 2мя гигами ОЗУ и 4-хгигагерцовым процессором страница генерировалась очень долго (от 3х секунд и больше). И это независимо от кеширования (что естесственно, т.к. все записи вытягиваются в sef.php в самом начале работы). После применения описанных изменений, страница генерируется не дольше 0.1 секунды. Думаю, разница заметна. Выводы делайте сами. Спасибо.
|
|
|
|
|
Записан
|
|
|
|
|
murat
|
 |
« Ответ #4 : 11.03.2007, 23:06:28 » |
|
У меня на сайте 27 статей. Стоит ли мне применять эти хаки? Ускорится ли зашрузка сайта?
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #5 : 11.03.2007, 23:12:48 » |
|
Считаю, что если и ускорится, то очень незначительно. Посмотрите, сколько записей в разделе Components - OpenSEF - Manage Friendly URLs. Их там должно быть не больше 100-200 (если больше -- надо почистить). Я уже писал, что хак имеет смысл применять если записей в меппинг-табличке больше нескольких тысяч. Проще говоря - Вы можете смело использовать оригинальный OpenSEF RC5 SP2 
|
|
|
|
|
Записан
|
|
|
|
userxp
Администратор
   
Репутация: +400/-6
Offline
Пол: 
Сообщений: 3227
Злой и ужасный бармалей
|
 |
« Ответ #6 : 11.03.2007, 23:21:36 » |
|
ну он не совсем оригинальный 
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #7 : 11.03.2007, 23:30:23 » |
|
Он оригинальный относительно тех изменений, который предлагаю я...
|
|
|
|
|
Записан
|
|
|
|
userxp
Администратор
   
Репутация: +400/-6
Offline
Пол: 
Сообщений: 3227
Злой и ужасный бармалей
|
 |
« Ответ #8 : 12.03.2007, 00:04:04 » |
|
я имел ввиду, что есть "оригинальный" RC5 + к нему SP2. а я на форуме выкладывал переделанный и локализованный RC5_SP2
|
|
|
|
|
Записан
|
|
|
|
moro
Новичок
Репутация: +0/-0
Offline
Сообщений: 4
|
 |
« Ответ #9 : 14.04.2007, 03:31:11 » |
|
Товарищи! Сказано: "Если хостер додумался включить кеширование запросов для MySQL - работать будет отлично". На мастерхосте ответили - не включено! Что же делать? имеет смысл использовать приведенные хаки? или подождать Вашего глубокоуважаемого экспертного мнения на этот счет? На самом деле - это реальная проблема - очень реальная. на сайте - около 300-400 статей и страницы грузятся по 20 секунд. хостер вопит - отрубает периодически. очень неприятно....
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #10 : 14.04.2007, 11:33:00 » |
|
Включайте! И дайте знать, если думать будет больше 3х секунд. Не забудьте про индексы для external и internal в табличке joom_opensef_sef.
|
|
|
|
|
Записан
|
|
|
|
|
murat
|
 |
« Ответ #11 : 14.04.2007, 13:03:01 » |
|
А как включить кэширование запросов для Mysql самостоятельно? У меня тоже хостер masterhost.
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #12 : 14.04.2007, 13:26:06 » |
|
Если у Вас есть доступ к /etc/my.cnf файлу, добавьте эти строки: query-cache-size=50M query-cache-type=1 key_buffer_size=128M Первые две строки включают кеширование запросов (с размером памяти можно экспериментировать, вплоть до 20% от общего количества RAM, установленного на сервере. Третья увеличивает объем памяти, отводимого под кеширование ключей и индексов. Тоже можно ставить до 20% от общего количества ОЗУ. Я ставил 5%. Но у меня очень большие нагрузки на веб-сервер (Apache). Экспериментируйте. В ближайшем будущем собираюсь написать статью об оптимизации сайта с Джумлой и всех ее подводных камнях. Следите за моим блогом  . Если будут какие-то вопросы еще с OpenSEF - не стесняйтесь, задавайте здесь или на блоге. Чем смогу, помогу. Удачи!
|
|
|
|
|
Записан
|
|
|
|
|
murat
|
 |
« Ответ #13 : 14.04.2007, 13:34:33 » |
|
у меня нет доступа к этому файлу.
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #14 : 14.04.2007, 13:43:27 » |
|
Тогда добавляйте индексы и пробуйте применить патчи. Не забудьте сделать бекапы изменяемых файлов. Все равно работать будет быстрее, чем с оригинальным OpenSEF. Сколько всего у Вас статей на сайте?
|
|
|
|
|
Записан
|
|
|
|
|
murat
|
 |
« Ответ #15 : 14.04.2007, 13:46:03 » |
|
немного. А что за индексы и куда их добавлять?
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #16 : 14.04.2007, 13:54:14 » |
|
Я уже, по-моему, писал -- если статей немного (меньше 1000), эти патчи Вам не нужны. Все и так работать должно нормально. Если какие-то проблемы и есть, то явно не от OpenSEF.
|
|
|
|
|
Записан
|
|
|
|
moro
Новичок
Репутация: +0/-0
Offline
Сообщений: 4
|
 |
« Ответ #17 : 22.04.2007, 21:57:44 » |
|
ну вот смотрите, какая картина: стоит Opensef последний,то есть Release Candidate 5 SP2. применен хак из первого поста alfim. проставлены индексы. Хостинг Мастерхост. То есть доступа к конфигурации сервера нет. Ограничения стандартные для этого хостера, то есть крутые. ПЛюс как мы знаем nginx. Работает шустро сначала (для чистоты эксперимента удалены все ЧПУ). Дальше при 1000 накопившихся ЧПУ - заметные тормоза. При 2000 ЧПУ - половина сайта демонстрирует 502 ошибку, в базе появляется много одинаковых ЧПУ (по два-три на одну и ту же страницу). При этом дебаг joomla показывает, что количество запросов к базе увеличивается в два раза по сравнению с отключенным OpenSEF.
Кто-нибудь видит решение? Такое впечатление, что для обеспечения работы сервера, надо очищать таблицу opensef_sef постоянно. Отказаться от OpenSEF можно, конечно, но не хочется, потому что сервер давно на нем стоит - поисковики все сожрали... Обидно терять позиции.
|
|
|
|
|
Записан
|
|
|
|
userxp
Администратор
   
Репутация: +400/-6
Offline
Пол: 
Сообщений: 3227
Злой и ужасный бармалей
|
 |
« Ответ #18 : 22.04.2007, 22:08:57 » |
|
на каких компонентах?
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #19 : 22.04.2007, 22:10:58 » |
|
moro, надо обязательно применить ОБА хака! ОБЯЗАТЕЛЬНО! Я же писал выше. Один только первый хак уложит вам сайт. Всерьез и надолго. ПРимените, и отпишитесь, пожалуйста.
Спасибо.
|
|
|
|
|
Записан
|
|
|
|
Димитрий
Осваиваюсь на форуме
 
Репутация: +0/-0
Offline
Пол: 
Сообщений: 106
Добра и счастья!
|
 |
« Ответ #20 : 27.04.2007, 16:57:13 » |
|
что значит уложит? я применил хак из 1го поста, и все очень быстро стало пахать. 1000 статей на сайте.
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #21 : 27.04.2007, 17:01:22 » |
|
То и значит  . Таблица SEF вырастет быстро, пойдут ошибки типа "you have no access" и так далее. Настоятельно советую применить и второй. Спасибо.
|
|
|
|
|
Записан
|
|
|
|
|
murat
|
 |
« Ответ #22 : 27.04.2007, 17:18:53 » |
|
А что вы думаете об этом: http://forum.j-prosolution.com/opensef-fixes/3493-code-optimization.html
|
|
|
|
|
Записан
|
|
|
|
userxp
Администратор
   
Репутация: +400/-6
Offline
Пол: 
Сообщений: 3227
Злой и ужасный бармалей
|
 |
« Ответ #23 : 27.04.2007, 17:23:36 » |
|
с точки зрения пхп это логично
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #24 : 27.04.2007, 17:27:02 » |
|
murat, только что отписался там. Не решает основную проблему -- вся табличка все-равно будет грузиться в память. На отечественных (украинских, русских) хостингах популярный сайт с большим количеством статей долго не проживет.
|
|
|
|
|
Записан
|
|
|
|
Димитрий
Осваиваюсь на форуме
 
Репутация: +0/-0
Offline
Пол: 
Сообщений: 106
Добра и счастья!
|
 |
« Ответ #25 : 02.05.2007, 23:54:36 » |
|
а подробнее? что значит популярный? и что значит с большим количеством статей? сколько заходов и сколько статей?
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #26 : 03.05.2007, 00:10:15 » |
|
Димитрий, я уже писал выше про ограничения. В числовом виде. Перечитайте еще раз 
|
|
|
|
|
Записан
|
|
|
|
Димитрий
Осваиваюсь на форуме
 
Репутация: +0/-0
Offline
Пол: 
Сообщений: 106
Добра и счастья!
|
 |
« Ответ #27 : 03.05.2007, 00:20:35 » |
|
Включайте! И дайте знать, если думать будет больше 3х секунд. Не забудьте про индексы для external и internal в табличке joom_opensef_sef.
я перешел на быстрый хостинг firstvds, и пошли тормоза с сефом.. 1000 статей,посещаемость 60 человек в день. генерится по 10 секунд. что делать? что за индексы, про которые вы пишите?
|
|
|
|
|
Записан
|
|
|
|
|
alfim
Гость
|
 |
« Ответ #28 : 03.05.2007, 00:22:44 » |
|
Индексы на соответсвующие поля в табличке jos_opensef_sef А хаки Вы применяли?
|
|
|
|
|
Записан
|
|
|
|
Димитрий
Осваиваюсь на форуме
 
Репутация: +0/-0
Offline
Пол: 
Сообщений: 106
Добра и счастья!
|
 |
« Ответ #29 : 03.05.2007, 00:24:50 » |
|
оба хака применил. все равно не понимаю, что за индексы. обьясните, если не сложно- для тех, кто в танке- что надо сделать? могу зайти через phpmyadmin и сделать данное действо. когда я был на другом хостинге все летало, сегодня перешел- сделал полную копию. сначала SEF показалось вообще не работал. просто висяк полный. посмотрел логи, там везде 404 стоит от яндекса-бота. потом переставил openSEF, стало жутко долго открывать- 10-20 секунд.
|
|
|
|
|
Записан
|
|
|
|
|