Microtime в PHP?

357
13 марта 2017, 11:54

Микросекунда это 1/миллионная секунды, но в php при microtime(true) никогда не удавалось увидеть значение больше 9999 после точки. Это внутреннее ограничение языка, системы? Или там где-то есть настройка которая весь миллион позволяет включить?

Answer 1

Это связано с количеством значащих цифр, отображаемых для чисел с плавающей точкой.

В php.ini поменяйте

precision = 14

на

precision = 16

например и снова посмотрите результаты работы функции.

Answer 2

Оставлю-ка я этот ответ просто в назидание.

Я сначала подумал, что такого понятия, как точка в double просто нет - есть экспонента и мантисса, поэтому надо проверить это дело в консоли и написать, что этого не может быть

etki@aves:/tmp > php -r 'var_dump(microtime());'
Command line code:1:
string(21) "0.74330500 1489303949"
etki@aves:/tmp > php -r 'var_dump(microtime());'
Command line code:1:
string(21) "0.43651800 1489303950"
etki@aves:/tmp > php -r 'var_dump(microtime());'
Command line code:1:
string(21) "0.26226800 1489303951"

И на этом этапе, видя 00 в конце дробной части секунд, сходу принимаю это за округление до сотни микросекунд (что, конечно, неверно - округление идет до одной микросекунды). Дальше - оригинальный ответ с небольшой редакцией

Чтобы найти причины поведения, можно залезть в исходники PHP. На третьей странице поиска по очевидном запросу находится то, что нам нужно: ext/standard/microtime.c. Дальше можно проследить, что за функция вызывается при вызове microtime: _php_gettimeofday, а она, в свою очередь, вызывает gettimeofday из C API.

Здесь уже можно отправлять в гугл запрос gettimeofday resolution и получать много разных ссылок на en.so и не только, в которых будут ссылаться на статьи по работе часов в Linux, но можно пойти еще дальше

  • do_gettimeofday
  • getnstimeofday64
  • __getnstimeofday64
  • timekeeping_get_ns
  • timekeeping_get_delta

Здесь уже начинается темная магия, для которой все-таки надо понимать ядро Linux получше меня, но можно отметить, что используется некоторая структура clocksource:

* @read:               returns a cycle value, passes clocksource as argument
...
* @mult:               cycle to nanosecond multiplier
...

Очевидно, что clocksource считает какие-то циклы, которые затем преобразует в наносекунды путем умножения и деления (видимо, это абстракция над TSC в процессоре), а само количество наносекунд считается в виде long, из которого потом составляется вывод microtime. Таким образом можно сказать, что

  • PHP целиком и полностью полагается на API операционной системы, и не налагает каких-либо ограничений на возвращаемые данные (т.е. возможно, чтот тот же самый код на том же железе на новых версиях ОС будет выдавать иные значения)
  • Вывод microtime довольно странный. Если установить по совету @Visman precision в достаточно большое число, то количество ненулевых цифр после запятой может быть довольно большим:

    etki@aves:/tmp > php -r 'var_dump(microtime(true));'
    Command line code:1:
    double(1489304519.9542729854583740234375)

    Это явно излишняя точность, которую машина не может обеспечить; однако вывод microtime() по-прежнему выдает нули в конце дробной части:

    etki@aves:/tmp > php -r 'var_dump(microtime());'
    Command line code:1:
    string(21) "0.26226800 1489303951"

    Возможно, это происходит в результате конвертации в double, но делать какие-то выводы не берусь

В целом хотел бы заметить, что время - это очень скользкая тема, и полагаться на вывод microtime и аналогичных функций для организации логики не стоит (потому что они подвержены leap seconds, они имеют право возвращать на последующих вызовах значения меньше текущих, и т.д.)

READ ALSO
Оценка кода и что нужно знать джуниору?

Оценка кода и что нужно знать джуниору?

Здравствуйте! Я самоучка С++, и меня интересует, какие знания мне нужны, чтобы меня приняли на работуИ ещё вопрос: хватит ли моих нынешних знаний?...

322
Перегрузки в конструкторах классов

Перегрузки в конструкторах классов

Не нашел, что-то ответа на такой простой ответДо этого не делал в конструкторе перегрузки таким образом (см

287
Ошибка sdkddkver.h

Ошибка sdkddkver.h

Использую VS2013 - затем установил VS2015 для заданий по книгеНедавно открыл через VS2013 (на VS2015 также) старые проекты для OpenGL на С++ и всё стало красным...

303
Ссылка на массив указателей. C++

Ссылка на массив указателей. C++

Есть ли какой-нибудь способ сделать ссылку на массив указателей?

378