Скорость скрипта.

Voyager2K

Новичок
Скорость скрипта.

Дело такое... Есть строка $line, нужно разбить ее на массив ключ-значение.

Ниже приведен код, где в первом варианте я регулярками(причем для каждого значения отдельно регулярку запускаю) разбиваю.
Во втором варианте, думал сравнить насколько быстрей получится вручную посимвольно пробежаться по строке и выцепить необходимые значения. Вот только не успел, сделал только дабы цикл опсимвольно пробегал строку и выводил ее... и уже тут у меня полезли глаза на лоб(см. вывод скрипта т.е. время). Каким образом куча регулярок пробегают обрабатывают строку и формируют массив быстрее, нежели просто посимвольной пройти и вывести черех echo ? Или я сейчас ничего не соображаю ночью ?

PHP:
class CTimer
	{
	var $s;
	var $p = 0;

	function start()
		{
		$this->s = $this->getmicrotime();
		}

	function pause()
		{
		$this->p = $this->getmicrotime();
		}

   function unpause()
		{
		$this->s += ($this->getmicrotime() - $this->p);
		$this->p = 0;
		}

   function fetch($decimalPlaces = 3)
		{
		return round(($this->getmicrotime() - $this->s), $decimalPlaces);
		}

   function getmicrotime()
		{
		list($usec, $sec) = explode(" ", microtime());
		return ((float)$usec + (float)$sec);
		}
	}

echo 'begin<hr>';

$tm = new CTimer();


$line = '[DATE]=2006-02-16 07:31:01 [IP]=122.0.0.1 [TO]=http://wk_site1.loc/index.php?page=2   [FROM]=http://wk_site1.loc/index.php?page=2   [BROWSER]=Microsoft Internet Explorer [COOKIE]=true [RESOLUTION]=1400x1050';

/////////////////////////////////////   ВАРИАНТ 1
$tm->start();

$res = array();
preg_match('/\[DATE\]=(.+?)((?=$)|(\[[a-z0-9]+\]=))/i', $line, $r);
$res['DATE'] = $r[1];
preg_match('/\[IP\]=(.+?)((?=$)|(\[[a-z0-9]+\]=))/i', $line, $r);
$res['IP'] = $r[1];
preg_match('/\[TO\]=(.+?)((?=$)|(\[[a-z0-9]+\]=))/i', $line, $r);
$res['TO'] = $r[1];
preg_match('/\[FROM\]=(.+?)((?=$)|(\[[a-z0-9]+\]=))/i', $line, $r);
$res['FROM'] = $r[1];
preg_match('/\[BROWSER\]=(.+?)((?=$)|(\[[a-z0-9]+\]=))/i', $line, $r);
$res['BROWSER'] = $r[1];
preg_match('/\[COOKIE\]=(.+?)((?=$)|(\[[a-z0-9]+\]=))/i', $line, $r);
$res['COOKIE'] = $r[1];
preg_match('/\[RESOLUTION\]=(.+?)((?=$)|(\[[a-z0-9]+\]=))/i', $line, $r);
$res['RESOLUTION'] = $r[1];

$rt = $tm->fetch(9);

print_r($res);
echo '<br><H2> TIME '.$rt.'</H2><hr>';

////////////////////////////////////////////  ВАРИАНТ 2

$tm->start();

$length = strlen($line);
for ($i = 0; $i < $length; $i++)
	{
	echo $line[$i];
	}

$rt = $tm->fetch(9);

//print_r($res);

echo '<br><H2> TIME '.$rt.'</H2><hr>';

Какие результаты у меня выдает:

begin
--------------------------------------------------------------------------------
Array ( [DATE] => 2006-02-16 07:31:01 [IP] => 122.0.0.1 [TO] => http://wk_site1.loc/index.php?page=2 [FROM] => http://wk_site1.loc/index.php?page=2 [BROWSER] => Microsoft Internet Explorer [COOKIE] => true [RESOLUTION] => 1400x1050 )

TIME 0.000124931

--------------------------------------------------------------------------------
[DATE]=2006-02-16 07:31:01 [IP]=122.0.0.1 [TO]=http://wk_site1.loc/index.php?page=2 [FROM]=http://wk_site1.loc/index.php?page=2 [BROWSER]=Microsoft Internet Explorer [COOKIE]=true [RESOLUTION]=1400x1050

TIME 0.000168085
 

kost

Новичок
Вот мой резалт.

X-Powered-By: PHP/5.1.2
Content-type: text/html

[пропущено]
0.00180006
[пропущено]
0.003492117


----------------------------------------

P.S> А вот ф-цию unpause() следует переписать. Надо добавить проверку, если уже не на паузе, то ничего не делать. (фактически проверку p "на ноль"). Но это оспоримая точка зрения, так как сугубо ИМХО.

----------------------------------------

А. Ну да. Насчет темы). Думаю, это можно обьяснить тем, что выполнение скомпилированного C++-ного кода быстрее, чем парсинг пхп-шного. Больше причин не нахожу.
 

Voyager2K

Новичок
Все же интересно почему так получается. И как быстрее это реализовать...

А то конечная задача у меня обработать кучу таких лог-строк. То, что есть сейчас... работает с логами на 3.5 - 4 мега (около 18 000 - 19 000 записей в стиле вышеприведенного $line) приблизительно 2 с небольшим секунды, есстественно там накладывается мое корявое программирование на ООП еще. Но всеже без парсинга строки все это занимает 0.055 seconds, а с парсингом, хм... странно сейчас уже выдает 1.575 seconds (округления до тысячных), хотя раньше кажись около 2 секунд было(может я ошибался, может компьютер у меня проснулся наконец) .
В любом случае понятно, что это(парсинг) самое узкое место в системе... нужно как-то его ускорить. Но вот как ?

P.S> А вот ф-цию unpause() следует переписать. Надо добавить проверку, если уже не на паузе, то ничего не делать. (фактически проверку p "на ноль"). Но это оспоримая точка зрения, так как сугубо ИМХО.
Хм, ну это вообще не мой класс... просто по php.net лазил, в одном из комментов увидел. Не знаю чем она мне приглянулась, но копирнул себе. Тебе под рукой удобный бенчмарк =) Конечно не такие махины: http://pear.php.net/packages.php?catpid=2&catname=Benchmarking , но то что мне нужно делает
 

kost

Новичок
Вот решение вашей проблемы.
PHP:
class CTimer

// пропущено

/////////////////////////////////////   ВАРИАНТ 1

// пропущено

////////////////////////////////////////////  ВАРИАНТ 2

$tm->start();

$length = strlen($line);
$str = '';
for ($i = 0; $i < $length; $i++)
    {
    $str .= $line[$i];
    }

echo $str;

$rt = $tm->fetch(9);

//print_r($res);

echo '<br><H2> TIME '.$rt.'</H2><hr>';
Резалт:
0.002176046
0.000329018
 

Voyager2K

Новичок
kost всмысле сначала в переменную все класть ? Я так пробывал, сейчас еще раз перепроверил. Результаты как и получались еще хуже, так и получаются.

TIME 0.000123024
TIME 0.000194073

Возможно от php-версии это все зависит. У меня 4.4.0

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

PS. Хоть вешайся. Неужели прейдется идти вспоминать Дельфи, может там хорошей производительности удасться добится...
 

kost

Новичок
Voyager2K
> PS. Хоть вешайся. Неужели прейдется идти вспоминать Дельфи, может там хорошей производительности удасться добится...

Вспоминать стоит. А точно стоит? Может регулярками? Или совсем надо быстро? Если уж вспоминать, то только не Делфи, а C++ (для таких вещей быстрее). Тем более, что Делфи под линух или freeBSD я, честно говоря, не видал. Только free pascal. Тем более, что генераторы C++-кода парсеров уже есть. Копайте в сторону BYACC и BISON.
 

Voyager2K

Новичок
что Делфи под линух или freeBSD я, честно говоря, не видал
Оть первый попавший обзорный линк на kylix http://www.delphimaster.ru/articles/kylix2/index.html
Но у меня задача под винду в любом случае писать эту штуку. Скорость достаточно важный критерий т.к. из $line можно было понять,что это логи посещений. Не составит труда прикинуть какого размера они достигнут с сайта, например, 5 000 хитов/день за месяц. И что будет с бедным человеком, решившим получить отчеты за весь период =) Не выдавать же ему мессагу: "Уважаймы юзВерь, сходите пока приготовьте себе завтрак/обед/ужин, заварите чащечку кофе и запаситесь газеткой для приятного времяприпровождения... и самое главное не забудьте выставить в php.ini max_execution_time в 999999999999 !" Просто на пхп я начал писать по свежей памяти т.к. остального почти ничего не знаю или почти не знаю. Хотя не спорю, затея бредовая, но жалко бросать на пол-пути.

Не знаю уж насколько дельфи тормознута, и насколько производительность будет выше чем php-вариант и ниже С-шных решений. Просто с торону С я вообще нУль. Хотя, чувствую если изучу его на базовом уровне, то при последующей деятельности он мне многократно пригодится... Вообщем я "на измене" ;)
 

Фанат

oncle terrible
Команда форума
Не составит труда прикинуть какого размера они достигнут с сайта, например, 5 000 хитов/день за месяц. И что будет с бедным человеком, решившим получить отчеты за весь период
а, типа, единственный способ получить отчёты за весь период - это парсить текстовые логи за весь период.
а правильно понял эту гениальную мысль?
 

Rammstein

PHPClub::News
Ну тут и гении собрались.

А вы про такую вещь как кэш не слышали? Советую ознакомиться. Если без мозгов подходить к разработке, то вскоре нужно будет заказывать супер-компьютер у Sun Microsystems для вашего хомяка.

Короче, подумал тут... не буду напрягать: просто ежедневно по крону или чё там ещё есть, запускайте скрипт, который за сутки все данные будет пихать в БД, а ещё лучше, сбивать данные по суткам (уменьшите скорость обработки и количество занимаемого места БДой; хотя и зависит от задачи). А там по желанию можно и чистить лог, чтобы в следующий раз не грузить лишнего в память при обработке.
 

Voyager2K

Новичок
а, типа, единственный способ получить отчёты за весь период - это парсить текстовые логи за весь период.
Не хотелось бы припрягать БД, если ты про это. Я бы сейчас начал объяснять почему... но это долго. Если объясню кратко, опять недопонимание и наезды пойдут. В любом случае собирался переделывать все на обычный виндовый софт, но просто вопрос времени когда: раньше думал так протянуть месяцев несколько =) Сейчас уж не знаю. Под БД, хоть волокиты и не много, но не хочется как-то...

А вы про такую вещь как кэш не слышали
Не совсем понял в какую сторону намек... ?
 

Фанат

oncle terrible
Команда форума
при чём здесь БД?
Милай, ты вообще соображаешь, что делаешь?
ты собираешься сделать систему, которая ПО ЛЮБОМУ запросу должна перелдопачивать ЛЮБОЙ объём логов за ограниченное время!
Ты, по-моему, потерял всякую связь с реальностью. И делаешь что-то из разряда "пойди туда, не знаю куда".

Если такой ужас у тебя вызывает систематизация и индексация данных в БД, то хотя бы сделать все отчёты за прошлые периоды ОДИН раз, и потом только дёргать статику (тот самый кэш, про который тебе говорят) - тебе в голову не приходило?

слушай, ты бы посмотрел хоть сущестуюущие-то решения, а?
 

Voyager2K

Новичок
Фанат вот чего я и боялся. Недопонимание.

Но все же, любопытно, как ты себе представляешь кэширование абсоолютно разношерстных отчетов ? Фильтры по полям различные: на регулряках, с помощью списков значений из файла и т.д. Просто группировака значений за месяц не покатит даже по той причине, что в выдаче должны присутсвовать все записи отдельно. Кэшировать выдачу ? Например закэшировать резалт запроса: "где ip 125.*.*.125 за период 2 месяцев с промежутком времени 8:00 до 12:00", а юзер в следующий раз сделает запрос: "где ip list (125.1.1.0 или 111.111.11.1) и где разрешение экрана НЕ 800x600 за период 3 месяцев". Вывод в обоих случаях производить в формате [IP],[TO],[FROM],[BROWSER],[COOKIE],[RESOLUTION] записей, удовлетяорящий фильтрам. И куда плыть с кэшем ? Какие данные в каком формате хочешь предложишь кэшить ?

ЗЫ. Есстествно логи не все перелопачиваются, если это не нужно (лимит постраничной выдачи достигнут, ограничение по дате и тд).
 

Фанат

oncle terrible
Команда форума
вот чего я и боялся. Недопонимание.
бойся собственной глупости. а паче того - упёртости.
умный человек, если с ним не соглашаются, начинает сомневаться в своих выводах. Дурак - в том, что его понимают.
Но все же, любопытно, как ты себе представляешь кэширование абсоолютно разношерстных отчетов ?
Очень хорошо представляю.
по выдаче webalizer-а
Какие данные в каком формате хочешь предложишь кэшить ?
все. в бд. которая вызывает у тебя ужас.
 

Voyager2K

Новичок
бойся собственной глупости... ( и т.д. "оскорбления")
Хм, позволь продолжу.... но ни одному из них неприятны, пусть и косвенные, оскорбления.

Очень хорошо представляю.
по выдаче webalizer-а
Это уже Си. Совсем другая опера. Вскоре как раз на Си буду переделывать тогда и загляну туда. А сейчас я там ничего не пойму(надеюсь ранние посты этого топика ты читал), а с просьбой помочь разобраться че же там... одними оскорблениями в мой адрес я не отделаюсь.

Мне понравилось(читаем "через строчку" предыдущие посты), наверное когда я, если такое будет, то же стану крутым пхп-гуру, смогу так же неопределенно мылсить... :
Фанат: а, типа, единственный способ получить отчёты за весь период - это парсить текстовые логи за весь период?
Voyager2K: Не хотелось бы припрягать БД
Фанат: при чём здесь БД?
Voyager2K: Какие данные в каком формате хочешь предложишь кэшить ?
Фанат: все. в бд. которая вызывает у тебя ужас.
 

Фанат

oncle terrible
Команда форума
ты просто чудовищный тормоз.
вместо того, чтобы менять подход, ты пытаешься выцыганить пару процентов производительности, и УПЕРЕТЬСЯ в ТЕ ЖЕ САМЫЕ проблемы с ростом объёма логов.
ну перепишешь ты на С. логи вырастут, и опять будет то же самое. что дальше? ассемблер?
давай-давай. флаг в руки.

идиот. это готовые отчёты. то самое кэширование.

-~{}~ 18.06.06 22:42:

не хочешь базу данных - сделай какой-то её аналог.
Но почему ты стольк остервенело цепляешься за идиотскую идею по каждому запросу парсить все логи - для меня загадка.
 

denver

?>Скриптер
Voyager2K
Не туда смотришь с оптимизацией. Фанат прав. Есть ли смысл выкидывать весь балласт когда проше с ручника снять?
 

Voyager2K

Новичок
Пожалуйста, здравомысляшие люди, что остались тут и читают этот топик... внезойдите до помощи. А то я своей непонятливостью вон уже одного человека довел до слюне- и сопле-метания. Каюсь, не хотел. Лечение бы не пришлось бы оплачивать... =) Хочу, последующим своим вопросом на примерах все понять для себя: действительно ли я туплю, или народ невнял мой вопрос т.к. я его плохо изложил.

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

[DATE]=2006-01-01 10:00:00 [IP]=192.168.0.1 [TO]=/index.html [FROM]= [BROWSER]=Opera [RESOLUTION]=800x600

[DATE]=2006-01-01 10:05:00 [IP]=192.168.0.2 [TO]=/news.html [FROM]=/about.html [BROWSER]=IE [RESOLUTION]=1024x768

[DATE]=2006-01-01 10:10:00 [IP]=192.168.0.1 [TO]=/page1.html [FROM]=/index.html [BROWSER]=Opera [RESOLUTION]=800x600

[DATE]=2006-01-01 10:15:00 [IP]=192.168.0.2 [TO]=/humor.html [FROM]=/news.html [BROWSER]=IE [RESOLUTION]=1024x768

[DATE]=2006-01-01 10:20:00 [IP]=192.168.0.2 [TO]=/humor_new.html [FROM]=/humor.html [BROWSER]=IE [RESOLUTION]=1024x768

[DATE]=2006-01-01 10:25:00 [IP]=192.168.0.1 [TO]=/page2.html [FROM]=/page1.html [BROWSER]=Opera [RESOLUTION]=800x600

[DATE]=2006-01-01 10:30:00 [IP]=192.168.0.1 [TO]=/page3.html [FROM]=/page2.html [BROWSER]=Opera [RESOLUTION]=800x600


Что бы сделал, например, тот же webalizer(который мне так впаривали как пример, почему я так и не понял) для анализа логов ? Он бы один раз пробежался по логу и сформировал HTML-ку... типа (если, допустим, отчет формируется ежедневно в отдельный хтмл)
<..опускаем тэги..>
<TABLE>
<TR><TD>хитов</TD><TD>7</TD></TR>
<TR><TD>Хостов</TD><TD>2</TD></TR>
<TR><TD>Браузер IE</TD><TD>3</TD></TR>
<TR><TD>Браузер Opera</TD><TD>4</TD></TR>
</TABLE>
<..опускаем тэги..>
Вообщем ряд таких ХТМЛ-отчетов, выдаваемые данные которых известны.

Но, что будет, если неизвестно, что выводить ? Зашел юзер и дал запрос(повторяюсь который раз, юзер может дать абсолютно любой запрос на совпадение(регуляркой или неким схожим "гибким" синтаксисом) по любому полю или группе полей):
хочу видеть все записи где поле [TO] содержит подстроку "page", за период времени с 2006-01-01 10:12:00 до 2006-01-01 10:29:00, где заход производился с браузера Opera
В данном примере в выводе запроса будет лишь одна строка. Каким образом, если я буду формировать отчеты в стиле webalizer'a, я смогу использовать уже готовый output(в стиле вышепривиденного) для обработки этого запроса пользователя ? Или может как-то иначе нужно кэшировать "переваренные" логи, дабы быстро находить требуемую инфу ? Подскажите на данному примере лога и запроса, как должны выглядеть кэш данные т.е. их устройство.

Помогите с ручника снять &copy; denver

P.S. А то я пока все так же убежден, что нет вомозжности организовать так структуру хранения данных в стиле output'ов заготовленных, что бы можно было получить ответ на любой запрос... т.к. для ответа на запрос скрипту понадобится ВСЯ информация о каждой записи, а занчит неизбежен обход лога.
 

Black Raven

Новичок
Не буду оригинальным...
юзай БД - она 100% будет работать быстрее, чем велосипед-эмуляция-текстовой-бд...

у меня для статистики 3 таблицы, уже 2 млн. записей в каждой и + 5000-7000 в день опять же в каждую...

вот теперь встал вопрос о кешировании (по крону в статику гнать, но у меня наверно 20 вариантов по которым подготавливается эта статика)

ну если ты считаешь что вариантов выборки прямо таки нереальное количество (что очень сомнительно), то можешь такие костыли:
1. Пользователь делает запрос
2. система смотрит наличие статики (например пусть все параметры поиска в одну строку и md5 (например) чтобы получилась "уникальная" строка" - пусть станет именем файла кеша)
3.1 статики нету - выдаем страницу "генерируем отчет" и запускаем в бэкграунде скрипт обработки логов, переодическим обновлением "статусной" страницы проверяем завершился скрипт формирования статики или нет, как появляется статика - выдаем
3.2 статика есть - выдаем статику

ну и естественно не надо хранить ВСЁ в одном логе - пусть будет логическая структура у логов - директория год, директория месяц, файл - день...

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

Rammstein

PHPClub::News
Voyager2K
Тебя уже с ручника третьи сутки снимают.
Посчитай сколько раз тебе говорят о "минимум перенос логов в БД" и сделай выводы.
 
Сверху