Войти

Показать полную графическую версию : Оптимизация запроса


venuko
01-04-2009, 20:36
Есть класс:

class highlighter
{
private $_string;
private $_words;
private $_opentags;
private $_usedTags = array();

public function __construct( $string, $words, $opentags )
{
$this->_string = $string;
$this->_words = $words;
$this->_opentags = $opentags;
}

private function countWordLength( $wordForms )
{
$formsNum = count( $wordForms );
$len = 0;
for( $j = 0; $j < $formsNum; $j++ )
{
$len += strlen( $wordForms[$j] );
}
$len = $len / $formsNum;
return $len;
}
private function swap( &$var1, &$var2 )
{
$temp = $var1;
$var1 = $var2;
$var2 = $temp;
}
public function prepareWordArray()
{
$wordsNum = count( $this->_words );
$words = $this->_words;
$opentags = &$this->_opentags;
$closetags = &$this->_closetags;
$n = 1;
while( $n != 0)
{
$n = 0;
for( $i = 0; $i < ( $wordsNum - 1 ); $i++ )
{
$len1 = $this->countWordLength( $words[$i] );
$len2 = $this->countWordLength( $words[$i + 1] );
if( $len1 < $len2 ) {
$this->swap( &$words[$i], $words[$i + 1] );
$this->swap( &$opentags[$i], $opentags[$i + 1] );
$n++;
}
}
}
$this->_words = $words;

}

private function isWord( $pos, $len)
{
$chars = ".?()[]\"',/\\ !@#$%^&*{}<>`~№;:?";
$string = $this->_string;
$a = $b = true;
if ($pos > 1) {
if (strpos($chars, $string[$pos - 1])===false) {
$a = false;
} else {
}
}
if (substr( $string, $pos - 6, 6) == '<used>') {
return false;
}
if( substr( $string, $pos + $len, 7) == '</used>') {
return false;
}
if (isset( $string[$pos + $len] )) {
if (strpos( $chars,$string[$pos + $len] )===false ) {
$b = false;
} else {
}
}
if ($a && $b) {
return true;
} else {
return false;
}
}

public function findWordForms( $wordID )
{
$forms = $this->_words[$wordID];
$formsNum = count( $forms );
$string = &$this->_string;
$minPos = strlen( $string );
$minLen = 0;
$found = false;
for( $i = 0; $i < $formsNum; $i++ )
{
$stringLen = strlen( $string );
$word = $forms[$i];
$pos = 0;
$len = strlen( $word );
$next = false;
while ( ( $pos + $len ) < $stringLen )
{
$pos = stripos( $string, $word, $pos );
if ( $pos === false ) {
break;
}
if ($this->isWord( $pos, $len )) {
if( $pos < $minPos ) {
$minPos = $pos + 6;
$minLen = $len;
$found = true;
}
$word = substr( $string, $pos, $len );
$string = substr_replace( $string, '<used>'.$word.'</used>', $pos, $len )."\n";
$next = true;
break;
} else {
}
$pos += $len;
}
}
if( $found ) {
if (!in_array( $this->_opentags[$wordID], $this->_usedTags )) {
$word = substr( $string, $minPos - 6, $minLen + 13 );
$string = substr_replace( $string, $this->_opentags[$wordID].$word.'</a>', $minPos, $minLen);
$this->_usedTags[] = $this->_opentags[$wordID];
}

}
}
public function highlight()
{
$n = count( $this->_words );
for( $i = 0; $i < $n; $i++ )
{
$this->findWordForms( $i );
}
}

public function getResult()
{
$this->prepareWordArray();
$this->highlight();
$string = & $this->_string;
$string = str_replace( array( '<used>', '</used>'), array( '', '' ), $string );
return $this->_string;
}
}

В массив выводятся слова и ссылки:

$result = $db->sql_query("select tid, title from ".$prefix."_table");
while ($crow=$db->sql_fetchrow($result)) {
$tid=$crow['tid'];
$words[]=array($crow['title']);
$open_tags[]="<a href=\"modules.php?name=Encyclopedia&op=content&tid=$tid\">";
}

Потом в контенте выделяются соотвественные слова из указанного массива выше:

global $words, $open_tags;
$class = new highlighter($text, $words, $open_tags);
echo $class->getResult();

В базе в таблице table всего 1200 записей, но когда грузится страница с контентом и идет эта обработка (выделение слов, оборачивание ссылками), страница грузится очень долго более 20 секунд!

Подскажите пожалуйста, как оптимизировать запрос?

Igor_I
03-04-2009, 21:09
Смотри сам на время обработки. При помощи такого приёма:
$mtime = explode (" ", microtime ()); //Считываем текущее время //Разделяем секунды и миллисекунды
$time_start = $mtime [1] + $mtime [0]; //Составляем одно число из секунд и миллисекунд //Записываем стартовое время в переменную
$q = 0;
########################################################################

while ($crow=$db->sql_fetchrow($result)) {
$tid=$crow['tid'];
$words[]=array($crow['title']);
$open_tags[]="<a href=\"modules.php?name=Encyclopedia&op=content&tid=$tid\">";
++$q;
}

#####################################################
$mtime = explode (" ", microtime ());
$time_end = $mtime [1] + $mtime [0]; //Делаем все то же самое, чтобы получить текущее время //Записываем время окончания в другую переменную
$total_time = ($time_end - $time_start); //Вычисляем разницу
echo '<br />'.$q.'<br />'.$total_time;


sql_fetchrow($result) - что-то не нашёл этого?

venuko
04-04-2009, 09:49
sql_fetchrow($result) - что-то не нашёл этого? »

Т.е. ?

скрипт выдал такие цифры:

1144
0.020478963851929


И как быть, что это значит?

Igor_I
04-04-2009, 17:04
Это значит
1144 цикла прошли за 0.02 секунды.
А если вот так.

$mtime = explode (" ", microtime ()); //Считываем текущее время //Разделяем секунды и миллисекунды
$time_start = $mtime [1] + $mtime [0]; //Составляем одно число из секунд и миллисекунд //Записываем стартовое время в переменную

########################################################################

$result = $db->sql_query("select tid, title from ".$prefix."_table");

#####################################################
$mtime = explode (" ", microtime ());
$time_end = $mtime [1] + $mtime [0]; //Делаем все то же самое, чтобы получить текущее время //Записываем время окончания в другую переменную
$total_time1 = ($time_end - $time_start); //Вычисляем разницу




$mtime = explode (" ", microtime ()); //Считываем текущее время //Разделяем секунды и миллисекунды
$time_start = $mtime [1] + $mtime [0]; //Составляем одно число из секунд и миллисекунд //Записываем стартовое время в переменную
$q = 0;
########################################################################

while ($crow=$db->sql_fetchrow($result)) {
$tid=$crow['tid'];
$words[]=array($crow['title']);
$open_tags[]="<a href=\"modules.php?name=Encyclopedia&op=content&tid=$tid\">";
++$q;
}

#####################################################
$mtime = explode (" ", microtime ());
$time_end = $mtime [1] + $mtime [0]; //Делаем все то же самое, чтобы получить текущее время //Записываем время окончания в другую переменную
$total_time2 = ($time_end - $time_start); //Вычисляем разницу
echo '<br />'.$q.'<br />'.$total_time1.'<br />'.$total_time2;

Если цифры опять будут маленькие, то либо не там ищешь, либо что-то путаешь.

В таком случае 2 варианта
1 http://tools.pingdom.com
2 Yslow для Firefox.

venuko
04-04-2009, 18:54
вот проверил:
1144
0.0097150802612305
0.023669004440308

Может это дело в том длинном классе?

Igor_I
05-04-2009, 12:40
venuko,
Ставь в начале скрипта
$mtime = explode (" ", microtime ()); //Считываем текущее время //Разделяем секунды и миллисекунды
$time_start = $mtime [1] + $mtime [0]; //Составляем одно число из секунд и миллисекунд //Записываем стартовое время в переменную

########################################################################

Это в конце скрипта.

#####################################################
$mtime = explode (" ", microtime ());
$time_end = $mtime [1] + $mtime [0]; //Делаем все то же самое, чтобы получить текущее время //Записываем время окончания в другую переменную
$total_time1 = ($time_end - $time_start); //Вычисляем разницу

echo '<br />'.$total_time1;

Как варант - не парсить каждый раз заново текст, а сохранять его.

venuko
05-04-2009, 18:00
0.018907070159912


Кажется у хостера проблемы с nginx, так как на этом айпи все сайты также грузятся, елки

Igor_I
06-04-2009, 00:11
Можно адресок?




© OSzone.net 2001-2012