forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   PHP / MySQL (http://forum.boolean.name/forumdisplay.php?f=135)
-   -   Странное поведение microtime (http://forum.boolean.name/showthread.php?t=15159)

Phantom 21.07.2011 07:00

Странное поведение microtime
 
На компьютере под Windows XP установлен PHP 5.2.17.17
Замечаю странное поведение функции microtime(). Ставил в коде метки для быстрого тестирования скорости выполнения MySQL запросов:
Код:

$time=microtime(true);
// тут код запроса, но это по сути не важно, проблема в другом
echo round(microtime(true)-$time,5);

К моему удивлению этот код считает время как ему вздумается и часто выдаёт даже отрицательные результаты. Всегда пользовался данным методом, проблем никогда не было ни на одном сервере, ни на денвере на ноутбуке (там стоит более старая версия php). Решил разобраться в чём дело, запустил многократно в консоли такой код:
Код:

      $a=time();
      // $a вычитается для того, чтобы убрать целую часть и видеть больше чисел после запятой
      echo (microtime(true)-$a)."\r\n";
      usleep(10);
      echo (microtime(true)-$a)."\r\n";
      usleep(10);
      echo (microtime(true)-$a)."\r\n";
      usleep(10);
      echo (microtime(true)-$a)."\r\n";
      usleep(10);
      echo (microtime(true)-$a)."\r\n";
      usleep(10);
      echo (microtime(true)-$a)."\r\n";
      usleep(10);
      echo (microtime(true)-$a)."\r\n";
      usleep(10);
      echo (microtime(true)-$a)."\r\n";

По какой-то, неведомой мне причине, числа часто идут не в порядке возрастания, а как попало. Например число в середине списка может оказаться меньше предыдущего, а последующие опять в порядке возрастания. Или может выдать подряд штук по 5 одинаковых чисел, вплоть до миллионных долей.

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

Вместе с PHP тут установлен ZEND оптимизатор, не знаю имеет ли это значение, раньше никогда с ним не связывался.

Откуда PHP берёт значение microtime? У операционной системы ведь? Может XP глючит? Какие есть теории? может кто-то сталкивался с подобной проблемой.

UPD:
Всё сильнее кошу на проказы операционной системы. Запустил скрипт в консоли через интерпретатор Денвера (того, что стоит на ноутбуке и работает без нареканий), но на данном компьютере. Проблема имеет место быть. Видимо, это вопрос уже не по PHP, но всё таки, может кто-то с таким сталкивался.

Randomize 21.07.2011 09:14

Ответ: Странное поведение microtime
 
С незапамятных времён использую следующий класс собственного написания:
PHP код:

class Benchmark
{
    public 
$startTime 0;
    public 
$endTime 0;

    private function 
getmt()
    {
        
//return array_sum(explode(" ", microtime()));
        
return microtime(TRUE);
    }

    public function 
start()
    {
        
$this->startTime $this->getmt();
    }

    public function 
stop()
    {
        
$this->endTime $this->getmt();
    }

    public function 
get($round 2)
    {
        if (
$this->startTime === 0)
        {
            return (
'Before using <b>' __FUNCTION__ '</b> , you should first start the timer!');
        }
        return 
number_format(($this->endTime $this->startTime), $round'.''');
    }




Испоьзование:

PHP код:

// require_once 'Benchmark.class.php';
$b = new Benchmark();
$b->start();
sleep(1); // sleep one second
$b->stop();
echo 
$b->get(); // ~ 1 sec 

Обрати внимание на приватный метод getmt:
PHP код:

private function getmt()
    {
        
//return array_sum(explode(" ", microtime()));
        
return microtime(TRUE);
    } 

В нём 2 способа получения этого самого микротайма:
1) старый через эксплод+эрэй_сум
2) новый через флаг в микротайме

Я заметил, что на некоторых серверах второй вариант выдаёт дико неточный результат, а первый работает всегда железно, но он через-жопный (ну согласитесь, там же массивы волохаются)
Попробуй у себя 2 варианта по очереди.

Апд: Запустил твой код у себя на сервере:
Цитата:

0.58410406112671
0.63313007354736
0.63548994064331
0.6358630657196
0.63662004470825
0.63760709762573
0.63862204551697
0.64616799354553
Фурычит

SBJoker 21.07.2011 10:27

Ответ: Странное поведение microtime
 
Многоядерные процессоры они такие, у каждого ядра своё время ;)

Phantom 21.07.2011 16:59

Ответ: Странное поведение microtime
 
Randomize, про метод с explode знал, но да, он черезжопный. Я похожий класс сам использовал ранее, тоже с explode, а потом открыл для себя Америку, что в microtime оказывается можно передавать параметр. Сейчас попробую, возможно поможет. Но использовать такое решение постоянно не хочется.
SBJoker, при запуске PHP скрипта в консоли, он никогда у меня в диспетчере задач не отбирает более 50% процессора, поэтому я делаю вывод, что PHP во время выполнения юзает только одно ядро (на машине двухядерный процессор).

Phantom 21.07.2011 17:20

Ответ: Странное поведение microtime
 
Протестировал вариант с array_sum(explode(" ", microtime()));
Выдаёт всё равно какие попало числа:

0.689378976822
0.689965963364
0.690943002701
1.8727850914
0.704999923706
0.704999923706
0.704999923706
0.704999923706

Phantom 21.07.2011 17:30

Ответ: Странное поведение microtime
 
На форуме softtime человек высказал предположение, что это совместный глюк Windows API и PHP засчёт того, что таймеры в винде итак не точные, а ещё и PHP тормозит. Я ответил:

Цитата:

Возможно данная проблема проявляется всегда, просто в настолько небольшой степени, что это незаметно. Разница в тысячную долю секунду особо большой роли не сыграет. Но у меня разница достигает более одной секунды иногда. Это ни в какие рамки не лезет. На компе проц AMD, на ноуте Intel. На обоих стоит WINDOWS XP с одного и того же физического носителя. Автообновление включено на обоих. Но раньше на компе стояла эта же винда и тот же самый интерпретатор и проблемы не было насколько я помню (не думаю, что она бы прошла у меня мимо глаз). Поэтому я сейчас думаю, что тут какая-то проблема с конфигурацией системы (я тут в винде понаотключал ненужных сервисов, в реестре менял некоторые вещи, но не думаю, что я задел что-то такое, что может влиять на время).

SBJoker 21.07.2011 22:39

Ответ: Странное поведение microtime
 
Цитата:

Сообщение от Phantom (Сообщение 196405)
Randomize, про метод с explode знал, но да, он черезжопный. Я похожий класс сам использовал ранее, тоже с explode, а потом открыл для себя Америку, что в microtime оказывается можно передавать параметр. Сейчас попробую, возможно поможет. Но использовать такое решение постоянно не хочется.
SBJoker, при запуске PHP скрипта в консоли, он никогда у меня в диспетчере задач не отбирает более 50% процессора, поэтому я делаю вывод, что PHP во время выполнения юзает только одно ядро (на машине двухядерный процессор).

Ты непонял меня.
Я и неговорил что пхп исполняется многопоточно. Дело в том что отдавая команду "поспать" процессу ты выводишь его из очереди на выполнение, и в следующий раз он может быть с 50% вероятностью для двухядерного процессора исполнен другим ядром. А время ядер никогда не совпадает так точно.

Phantom 21.07.2011 22:53

Ответ: Странное поведение microtime
 
Проблема возникает, даже без использования sleep и usleep.
Как можно решить эту проблему, если это она? Почему другие компы работают нормально? Я и раньше работал за этим компом, но это было давно, с тех пор там в нём много чего менялось, но процессор прежний. Раньше проблемы либо не было, либо я её не замечал (что маловероятно).

UPD:
Может можно как-то без негативных последствий отключить временно одно ядро и проверить останется проблема или нет?

Phantom 22.07.2011 19:40

Ответ: Странное поведение microtime
 
Думаю, что дальнейшее обсуждение проблемы продолжу на форуме Softtime, там поактивнее люди обсуждают. Кому интересно, вот ссылка: http://softtime.ru/forum/read.php?id...id_theme=81781
Когда решу проблему, решение напишу и тут.

Igor 22.07.2011 23:46

Ответ: Странное поведение microtime
 
Цитата:

Может можно как-то без негативных последствий отключить временно одно ядро и проверить останется проблема или нет?
Win 7: диспетчер задач>процессы>задать соответствие

Phantom 23.07.2011 16:24

Ответ: Странное поведение microtime
 
Цитата:

Win 7: диспетчер задач>процессы>задать соответствие
Уже провёл тесты. Судя по всему Джокер был прав. Если заставить PHP или Апач выполняться только одним из ядер, не важно каким, то проблема не проявляется вообще. Кроме того, чем дольше комп работает, тем время между ядрами рассинхронизуется всё сильнее и сильнее. Вот комп поработал несколько дней без выключения, так время вообще на 2 секунды уплыло. Прошил биос, уменьшил даже тактовую частоту с 2.300 до 2.200, сменил параметр оверклокинга с авто на стандарт. Не помогает, время всё равно спустя час работы компа "уплывает", но вроде немного медленнее, чем обычно. Может можно где-то в винде задать, через какое ядро ему время считать? Или как вариант, возможно, винда должна проводить какую-то синхронизацию между ядрами постоянно, но не делает этого из-за глюка/сбитых_настроек? Или что-то в этом роде?

Конфигурация компьютера:
Система:
Microsoft Windows XP Professional версия 2002 Service Pack 3
Компьютер:
AMD Athlon(tm) 64 X2 Dual Core Processor 4400+ 2.31 ГГц (уже 2.21 после смены настроек Биоса), 1.00 ГБ ОЗУ

Phantom 10.08.2011 12:19

Ответ: Странное поведение microtime
 
В общем, вот решение проблемы от самого Майкрософта: http://support.microsoft.com/kb/895980/
Хотя там оно заявлено как "временное", то есть костыль. Но всё работает и глюков не заметил в течении 2 с половиной недель использования.

Randomize 10.08.2011 12:51

Ответ: Странное поведение microtime
 
Спасибо! Буду иметь в виду.

impersonalis 26.01.2012 00:09

Ответ: Странное поведение microtime
 
Цитата:

Сообщение от SBJoker (Сообщение 196478)
Ты непонял меня.
Я и неговорил что пхп исполняется многопоточно. Дело в том что отдавая команду "поспать" процессу ты выводишь его из очереди на выполнение, и в следующий раз он может быть с 50% вероятностью для двухядерного процессора исполнен другим ядром. А время ядер никогда не совпадает так точно.

Прошу извинить за придирку и откапывание старых тем, но, возможно, это будет кому-то полезно.
Из книги Дж. Рихтера Windows для профессионалов: создание эффективных Win32 приложений с учетом специфики 64-разрядной версии Windows/Пер, англ - 4-е изд. - СПб; Питер; М.: Издательско-торговый дом "Русская Редакция", 2001. - 752 с.; ил.
Цитата:

По умолчанию Windows 2000 использует нежесткую привязку (soft affmity) потоков к процессорам. Это означает, что при прочих равных условиях, система пытается выполнять поток на том же процессоре, на котором он работал в последний раз. При таком подходе можно повторно использовать данные, все еще хранящиеся в кэше процессора
Т.е., в общем случае, 50% - завышенная оценка.
В остальном - Джокер первым верно указал проблему.

impersonalis 26.01.2012 18:13

Ответ: Странное поведение microtime
 
Прошу прощения ещё раз, но
Цитата:

Сообщение от SBJoker (Сообщение 196478)
А время ядер никогда не совпадает так точно.

Основная проблема всё же в том, что у разных ядер может быть разная, не равная номинальной частота, как следствие - разная производительность в тактах и разная скорость течения времени (если это не контролируется программой BIOS и дровами). Причина отличия частоты от номинала - технологии:
понижения частоты ядер AMD Cool'n'Quiet и Intel SpeedStep,
повышения частоты ядер AMD Turbo Core и Intel Turbo Boost.


Часовой пояс GMT +4, время: 02:45.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot