Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Точность функции microtime()


Автор: theworldcreator 12.7.2008, 20:34
Собственно проблема: пишу чат, существует скрипт, к которому каждые несколько секунд, через Ajax, обращается страница. В нем есть сессия(если еще нету, то создается), в которой метка time() предыдущего вызова этим пользователем. Дальше из БД берутся все сообщения с этой метки до момента сейчас, и этот момент сейчас, в свою очередь, записывается в сессию для следующего вызова.
Это была версия №1. Ее недостаток - если файл вызывался в начале секунды, то сообщения, добавленные в конце той же секунды не доходили до пользователя.
В следующий раз попробовал делать выборку до момента сейчас, НЕ включительно(то есть не " AND timestamp <='.$stime", а " AND timestamp <'.$stime").
Недостаток - зачастую приходиться очень долго ждать прихода сообщений. Сообщение уже пришло, но из за вышеописанной особенности не возвратилось вовремя и придется снова ждать таймера JS, вызывающего Ajax, снова ждать посылки запроса, ответа сервера....
Потом пришла в голову идея дождаться в PHP окончания текущей секунды, а потом сделать все тоже самое, как и в варианте №1. Но тут есть две проблемы: долго ждать ответа сервера, и я не знал загружает ли мой код ожидания сервер(если каждый вызов будет держать процессор загруженным по пол секунды никаких мощностей не хватит)
Поэтому решил попробовать с функцией microtime, как в варианте №3, дожидаться окончание текущий миллисекунды(этот способ лишен вышеописанных недостатков). Но это, разумеется, не сработает, если функция недостаточно точна(данная идея пришла в голову от того, что все говорят что профилер на ней точный невозможно построить)
Заранее спасибо за ответы, с уважением, Александр

Автор: theworldcreator 12.7.2008, 21:07
Код, вариант №3, для наглядности:
Код

$ctime = time();
if(empty($_SESSION['time_chat_update'])) $_SESSION['time_chat_update'] = 0;
while($ctime == time()){
    usleep(130);//добавлено, чтобы уменьшить нагрузку на процессор
}
$sql = 'select * from messages where mdate > '.$_SESSION['time_chat_update'].' AND mdate <= '.$ctime.' ORDER BY mdate DESC LIMIT 20';
$rs = mysql_query($sql);
while($r = mysql_fetch_array($rs)) {
    //заполнение массива сообщений
}
$_SESSION['time_chat_update'] = $ctime;

Автор: MuToGeN 12.7.2008, 21:14
Цитата(theworldcreator @  12.7.2008,  21:07 Найти цитируемый пост)
//добавлено, чтобы уменьшить нагрузку на процессор

Гениально. Вы случайно родом не из Индии?

Проблема, судя по всему, в кривизне структуры БД. Предлагаю выложить в этом топике полную ее схему.

Автор: theworldcreator 12.7.2008, 21:32
Цитата(MuToGeN @ 12.7.2008,  21:14)
Цитата(theworldcreator @  12.7.2008,  21:07 Найти цитируемый пост)
//добавлено, чтобы уменьшить нагрузку на процессор

Гениально. Вы случайно родом не из Индии?

Это промежуточный вариант,  все равно менять, и мысль двигалась в следующем направление: если пустые итерации цикла 100% займут процессор, то, скорей всего, встроенная функция откладывает продолжение выполнения скрипта, а не работает впустую. А поскольку этот вариант все равно промежуточный, реальное тестирование производительности было отложено до лучших времен.

Цитата
Проблема, судя по всему, в кривизне структуры БД. Предлагаю выложить в этом топике полную ее схему.


Изначально задача была такая: отдавать еще не прочитанные сообщения. Сразу пришли в голову две мысли: хранить где то список ID уже прочитанных(мне этот вариант показался очень ресурсоемким) или хранить где то время, по которое пользователь уже получил сообщения. Собственно здесь реализован второй вариант. Структура:
message    text
mdate    int(11)

Помимо этого есть еще несколько полей, но они сейчас никак не влияют.

Автор: gibbzy 16.7.2008, 13:31
а мне вообще кажется что микротайм это весьма относительно ведь ещё скорость выполнения скрипта до микротайма какая ? тоже же миллисикунды.

Автор: Fortop 16.7.2008, 15:22
theworldcreator, 
Цитата(theworldcreator @  12.7.2008,  20:34 Найти цитируемый пост)
Дальше из БД берутся все сообщения с этой метки до момента сейчас, и этот момент сейчас, в свою очередь, записывается в сессию для следующего вызова.

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

Т.е. на текущий момет ты получил сообщения по ID = 100 включительно.
Значит в следующий раз ты должен получить все сообщения которые имеют ID > 100

Так будет гораздо устойчивее.

Автор: theworldcreator 16.7.2008, 16:58
Хм, а об этом я не подумал. Спасибо большое!
Но таким образом решается лишь эта конкретная задача. Все равно очень интересно, насколько точно она работает, и если достаточно, то почему все ругаются на нее, как на основу профилера?

Автор: Feldmarschall 16.7.2008, 17:06
кто "все" и как именно "ругается"?
мало ли кто что скажет. глупостей говорят гораздо больше, чем умного. все опровергать времени не хватит

Автор: Sannis 16.7.2008, 17:13
Имхо проблема высосана из пальца. Неужели люфт в секунду так важен для обычного чата?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)