Блог пользователя - Demimurych

немного оптимизации или "Блок кто в сети" из ядрёного модуля user

9 января 2010 в 16:42

Вот кусок кода из user_block
отвечающий за составления списка пользователей онлайн.

$interval = time() - variable_get('user_block_seconds_online', 900);

          // Perform database queries to gather online user lists.  We use s.timestamp
          // rather than u.access because it is much faster.
          $anonymous_count = sess_count($interval);
          $authenticated_users = db_query('SELECT DISTINCT u.uid, u.name, s.timestamp FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= %d AND s.uid > 0 ORDER BY s.timestamp DESC', $interval);

Смотрим на запрос и думаем - а какого Художника был просто не сделан запрос к таблице users с условием по полю acceess

 $authenticated_users = db_query('SELECT u.uid, u.name, u.access  FROM {users} u WHERE u.access >= %d  ORDER BY u.access DESC', $interval);

обращаем внимание на комментарий выше, где нам пытаются обьяснить:
мол использование индекса из таблицы session это значительно быстрее чем использование чистой таблицы users и поля access

Мы не поверим автору и загляним в EXPLAIN
вводные
таблица SESSION 37МБ
таблица users 103МБ

О ЧУДО
Автор этого запроса явно МНОГО КУРИЛ БАМБУКА а не православного канабиса.

даже невооруженным глазом видно, что использование таблицы session не просто МАРАЗМ а еще и КРАЙНЕ ВРЕДНЫЙ МАРАЗМ
о чем ВОПИТ Using where; Using temporary; Using filesort

Попробуем все таки понять как ТАКОЕ могло попасть в ядро

История о том когда агрегация css/javascript вредна.

8 октября 2009 в 12:38

Обычно термин агрегация в рамках Drupal упоминают когда подразумевают процесс при котором все множество js css файлов собираются в один, соответствующий своему типу, файл. Тем самым добиваются уменьшения количества запросов к серверу что приводит, обычно, к снижению времени затраченное браузером на формирование страницы.

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

Имеем проект где активно используется jQuery и плагины к нему. Упакованный 1.2.6 сейчас занимает 30 килобайт.

Имеем две страницы
на первой используется(добавляется drupal_add_js) плагин my_plug_1 для jQuery величиной аж 1 килобайт.
На второй странице используется mu_plug_2 величиной аж 2 килобайта.

Имеем клиента с включенным в браузере кешем, делающего запрос к нашей странице номер 1.
Агрегатор включен.

произойдет следующее:
при загрузке первой страницы, агрегатор создаст файл с уникальным именем величиной JQuery + my_plug_1 = 31 килобайт.
при загрузки второй страницы создаст ЕЩЕ ОДИН УНИКАЛЬНЫЙ ФАЙЛ размером уже jQuery + my_plug_2 = 32 килобайта.

В результате из за агрегации, при запросе второй страницы вытаскивался код JQuery повторно. То есть лишних 30 килобайт.

Агрегатор выключен
при запросе первой страницы в коде двумя строками были бы указаны наши скрипты jQuery и my_plug 1. которые были бы закешированы бразуером.

к вопросу о оптимизации или небольшая задачка(с последующим решением) по my sql

7 октября 2009 в 18:08

Условие:
база данных содержит больше 100 000 нод. mysql сервер сконфигурирован таким образом что все индексы находятся в памяти.

Задача:
Выбрать nid всех нод статус которых 1 в порядке добавления последнего комментария.

Решение вроде бы тривиально

SELECT n.nid FROM node n
INNER JOIN node_comment_statistics ncs on n.nid = ncs.nid
WHERE n.status = 1 ORDER BY ncs.last_comment_timestamp DESC

индексы на status и last_comment_timestamp присутствуют.
однако, такой запрос будет выполняться 0.24 секунды на поиске первых 30 записей, и все дольше и дольше с каждой следующей пачкой.

Этот запрос можно привести к виду при котором он будет выполняться 0.001 секунды независимо от пачки.

Отгадка на картинке номер 3

tip's & trick's или неочевидный прием для увеличения производитенльости.

19 сентября 2009 в 23:21

Не многие обращали внимание, что например в 5 друале, формированием внешнего вида ЛЮБОЙ страницы занимается функция
theme('page')

Вроде бы что тут такого?

Но достаточно заглянуть в эту функцию чтобы понять, что именно в
function phptemplate_page

осуществляется вызов функций темизации для breadcrumb, сообщений, блоков и так далее, причем делается это независимо от того нужно это в шаблоне или нет.

Если Вы, как разработчик четко знаете что Вам нужно на странице, то перехватив функцию формирования страницы на себя например (function theme_name_page ), вы можете в отдельных случаях сократить время формирования страницы почти В ДВА РАЗА.

Как пример - стартовая страница на которой отсутствуют регионы и как следствие блоки.

То что описано ниже характерно для 5 ветки друпала. В 6 версии друпала делается нечто похожее организацией своей препроцесс функции формирования страницы.

Модуль Quote или почему нужно проводить аудит сторонних модулей.

14 сентября 2009 в 20:10

Ко мне обратился один знакомый, который обратил внимание на странное поведение некоторых страниц на его друпал сайте.
При запросе этих страниц, браузер показывал белую страницу.

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

после 5 минут работы в x_debug стало ясно, что виновником всему модуль quote, а точнее функция preg_replace_callback

function _quote_filter_process($text) {
if (stristr($text, '[quotе')) {
   
    $text = preg_replace_callback('#\[(quotе.*?)]((?>\[(?!/?quote[^[]*?])|[^[]|(?R))*)\[/quote]#is', '_quote_filter_process_callback', $text);
  }

  return $text;
}

Для людей умеющих навскидку читать регулярные выражения сразу становится понятно, что этот regexp занимается тем, что выделяет куски вида [ quote] ..... [/quote] сколь угодно любой вложенности.

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

Экспериментальным путем было установлено, что достаточно заключить в [ quote] данные обьемом в 13 килобайт чтобы php завершался аварийно.

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

Исправить положение можно заменив строку с регулярным выражением автора модуля на вот это

IE6 IFRAME суб домены третьего уровня и cookies

2 апреля 2009 в 11:49

Есть ресурс mydomain.com
На нем реализованы суб домены news.mydomain.com users.mydomain.com ...
Все это организовано таким образом что, авторизовавшись на mydomain.com пользователь остается таковым на субдоменах.

Возникла необходимость на суб домене открыть в iframe страницу с основного домена. Причем, эта страница доступна только авторизованному пользователю.
В результате все распространенные на сегодняшний день браузеры справились с этой задачей на отлично кроме ИЕ6. ИЕ6 показывал страницу access deny то есть так как будто ее запросил неавторизованный пользователь.

При более детальном изучении оказалось, что IE6 не посылает куки при подобной организации запроса. И что самое интересное, это касается ТОЛЬКО доменов третьего уровня. То есть, если бы например основной домен был home.mydomain.com а суб домены kv15.home.mydomaine.com то все бы работало и в ИЕ6.

Решение проблемы для ИЕ6 посылать специальный header

drupal_set_header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');

Объяснения от microsoft этого тут
http://support.microsoft.com/kb/323752/EN-US/

Shadowbox IE8 fix

29 марта 2009 в 15:40

В IE8 shadowbox отказался работать.

Фикс этого достаточно простой

Прописать следующий стиль в вашем скине (по умолчанию shadowbox/shadowbox/src/skin/classic/skin.css)

#shadowbox_title {
border: 0px solid;
}

#shadowbox_info {
border: 0px solid;
}

более подробно дискуссия тут

Cumulus решение многих проблем

7 декабря 2008 в 0:56

Многие видели наверное такой плагин для визуализации облака тэгов как
http://drupal.org/project/cumulus

и наверняка многие сталкивались с тем что в нем куча проблем с кирилицей, да и вообще проблем с отображением. То теги пропадут. То еще что то...

Решение почти всех проблем в замене cumulus.swf на более коректную версию. Которую я ниже и прилагаю.

Счетчик для сложной статистики от mail.ru или как удалось увеличить отзывчивость страинцы

29 ноября 2008 в 14:29

Один из моих знакомый обратился ко мне за советов в такой проблеме. На сайте использовался счетчик от mail.ru. Причем сложная форма этого счетчика которая предоставляет расширенную статистику посещения сайта. Установив это счетчик на свои страницы, знакомый обнаружил, что зачастую отзывчивость страниц упала в разы. То что открывалось за миллисекунды стало зависать порой на две три и больше секунд.

Вот пример кода счетчика (взят с чужого сайта)

<!--Rating@Mail.ru COUNTEr--><script language="JavaScript" type="text/javascript"><!--
d=document;var a='';a+=';r='+escape(d.referrer)
js=10//--></script><script language="JavaScript1.1" type="text/javascript"><!--
a+=';j='+navigator.javaEnabled()
js=11//--></script><script language="JavaScript1.2" type="text/javascript"><!--
s=screen;a+=';s='+s.width+'*'+s.height
a+=';d='+(s.colorDepth?s.colorDepth:s.pixelDepth)
js=12//--></script><script language="JavaScript1.3" type="text/javascript"><!--
js=13//--></script><script language="JavaScript" type="text/javascript"><!--
d.write('<a href="http://top.mail.ru/jump?from=1233906"'+
' target=_top><img src="http://d3.cd.b2.a1.top.mail.ru/counter'+
'?id=1233906;t=94;js='+js+a+';rand='+Math.random()+
'" alt="Рейтинг@Mail.ru"'+' border=0 height=1 width=1/><\/a><br>')
if(11<js)d.write('<'+'!-- ')//--></script><noscript><a
target=_top href="http://top.mail.ru/jump?from=1233906"><img
src="http://d3.cd.b2.a1.top.mail.ru/counter?js=na;id=1233906;t=94"
border=0 height=1 width=1
alt="Рейтинг@Mail.ru"/></a><br></noscript><script language="JavaScript"

Забавный глюк фильтра drupal.ru

29 ноября 2008 в 1:38

Вменяемый анти-xss

14 ноября 2008 в 18:30

Стоит ли говорить что одним из столпов серьезного проекта является его безопасность. Одной из проблем в этой области являются xss уязвимости. В апи друпала есть функция filter_xss назначение которой как раз бороться с этой головной болью.
НО
функционал ее до безобразия убог. И не приемлем в большинстве проектов, где в качестве форматирования ввода используется html, а не, например, bbcode. И вот почему:

filter_xss фильтрует "опасные" тэги целиком, а не ОПАСНЫЕ атрибуты тэгов.
Например у нас есть необходимость разрешить использование тэга img. Но при этом каждому Wink известно насколько опасно разрешать использование этого тэга целиком.

Выходит что использование стандартного апи нам тут ничем не поможет и нужно использовать что то серьезное вроде kses или аналогичные этому проекты.

Я уже было взялся писать свой фильтр(интегрирования kses в друпал), как опомнился и нашел на drupal.org замечательный модуль http://drupal.org/project/htmlpurifier который в том числе использует и kses.

Который всем и рекомендую.

простите за передеж в лужу.
Друпаловский filter xss хоть и деревянный как дуб дерево, но все таки позволяет фильтровать только опасные атрибуты, а не весь тэг целиком. Он конечно же не обладает той гибкостью как kses но вполне наджено и уверенно справляется со своей работой.

Моя ошибка была связана с тем что я при своих исследованиях не отключил сторонние фильтры которые и внесли сумятицу.

Записки разработчика таксономия taxonomy_get_term_by_name

9 октября 2008 в 11:28

Изучая внутренности таксономии (функционал и как он реализован на уровне кода) обнаружил интересную функцию
taxonomy_get_term_by_name($name)

которая возвращает данные по названию термина

$db_result = db_query(db_rewrite_sql("SELECT t.tid, t.* FROM {term_data} t WHERE LOWER('%s') = LOWER(t.name)", 't', 'tid'), trim($name));

забавно то что структура данных

CREATE TABLE `term_data` (
`tid` int(10) unsigned NOT NULL auto_increment,
`vid` int(10) unsigned NOT NULL default '0',
`name` varchar(255) NOT NULL default '',
`description` longtext,
`weight` tinyint(4) NOT NULL default '0',
PRIMARY KEY (`tid`),
KEY `vid` (`vid`)
) ENGINE=MyISAM AUTO_INCREMENT=44 DEFAULT CHARSET=utf8 AUTO_INCREMENT=44 ;

не содержит ключа для name

из чего следует что если таксономия будет использоваться очень обширно - использоваине этой функции крайне нежелательно. Либо добавить ключ
ALTER TABLE `term_data` ADD INDEX(`name`)