mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Implement high resolution monotonic timer function hrtime()
This commit is contained in:
parent
88b8cd7385
commit
83497327e7
11
UPGRADING
11
UPGRADING
@ -95,6 +95,17 @@ PCRE:
|
||||
6. New Functions
|
||||
========================================
|
||||
|
||||
Core:
|
||||
. Added monotonic timer function hrtime([bool get_as_num]). It returns an
|
||||
array of the form [seconds, nanoseconds] with the timestamp starting at
|
||||
an unspecified point in the past. If the optional argument is passed as
|
||||
true, the return value is an integer on 64-bit systems or float on
|
||||
32-bit systems, representing the nanoseconds. The timestamp is not
|
||||
adjustable and is not related to wall clock or time of day. The timers
|
||||
are available under Linux, FreeBSD, Windows, Mac, SunOS, AIX and their
|
||||
derivatives. If no required timers are provided by a corresponding
|
||||
platform, the function returns false.
|
||||
|
||||
Date:
|
||||
. Added the DateTime::createFromImmutable() method, which mirrors
|
||||
DateTimeImmutable::createFromMutable().
|
||||
|
@ -12,6 +12,7 @@ PHP 7.3 INTERNALS UPGRADE NOTES
|
||||
i. RAND_RANGE()
|
||||
j. cast_object() with _IS_NUMBER
|
||||
k. zend_fcall_info_cache.initialized
|
||||
l. php_hrtime_current()
|
||||
|
||||
2. Build system changes
|
||||
a. Unix build system changes
|
||||
@ -95,6 +96,9 @@ PHP 7.3 INTERNALS UPGRADE NOTES
|
||||
k. zend_fcall_info_cache.initialized is removed. zend_fcall_info_cache is
|
||||
initialized if zend_fcall_info_cache.function_handler is set.
|
||||
|
||||
l. php_hrtime_current() delivers the number of nanoseconds since an uncertain
|
||||
point in the past.
|
||||
|
||||
========================
|
||||
2. Build system changes
|
||||
========================
|
||||
|
@ -1453,6 +1453,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_http_response_code, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, response_code)
|
||||
ZEND_END_ARG_INFO()
|
||||
/* }}} */
|
||||
/* {{{ hrtime.c */
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_hrtime, 0)
|
||||
ZEND_ARG_INFO(0, get_as_number)
|
||||
ZEND_END_ARG_INFO()
|
||||
/* }}} */
|
||||
/* {{{ html.c */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_htmlspecialchars, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, string)
|
||||
@ -2986,6 +2991,8 @@ static const zend_function_entry basic_functions[] = { /* {{{ */
|
||||
PHP_FE(getrusage, arginfo_getrusage)
|
||||
#endif
|
||||
|
||||
PHP_FE(hrtime, arginfo_hrtime)
|
||||
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
PHP_FE(uniqid, arginfo_uniqid)
|
||||
#endif
|
||||
@ -3716,6 +3723,8 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
|
||||
|
||||
BASIC_MINIT_SUBMODULE(random)
|
||||
|
||||
BASIC_MINIT_SUBMODULE(hrtime)
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -13,14 +13,14 @@ int main(int argc, char **argv)
|
||||
char *filename = tmpnam(NULL);
|
||||
char buffer[64];
|
||||
int result = 0;
|
||||
|
||||
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
if (NULL == fp)
|
||||
return 0;
|
||||
fputs("line 1\n", fp);
|
||||
fputs("line 2\n", fp);
|
||||
fclose(fp);
|
||||
|
||||
|
||||
fp = fopen(filename, "rb+");
|
||||
if (NULL == fp)
|
||||
return 0;
|
||||
@ -58,7 +58,7 @@ if test "$ac_cv_func_crypt" = "no"; then
|
||||
AC_DEFINE(HAVE_CRYPT, 1, [ ])
|
||||
])
|
||||
fi
|
||||
|
||||
|
||||
AC_CACHE_CHECK(for standard DES crypt, ac_cv_crypt_des,[
|
||||
AC_TRY_RUN([
|
||||
#if HAVE_UNISTD_H
|
||||
@ -124,7 +124,7 @@ int main() {
|
||||
char salt[15], answer[40];
|
||||
char *encrypted;
|
||||
|
||||
salt[0]='$'; salt[1]='1'; salt[2]='$';
|
||||
salt[0]='$'; salt[1]='1'; salt[2]='$';
|
||||
salt[3]='r'; salt[4]='a'; salt[5]='s';
|
||||
salt[6]='m'; salt[7]='u'; salt[8]='s';
|
||||
salt[9]='l'; salt[10]='e'; salt[11]='$';
|
||||
@ -267,7 +267,7 @@ else
|
||||
AC_DEFINE_UNQUOTED(PHP_USE_PHP_CRYPT_R, 0, [Whether PHP has to use its own crypt_r for blowfish, des and ext des])
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl
|
||||
dnl Check for __attribute__ ((__aligned__)) support in the compiler
|
||||
dnl
|
||||
AC_CACHE_CHECK(whether the compiler supports aligned attribute, ac_cv_attribute_aligned,[
|
||||
@ -289,7 +289,7 @@ dnl
|
||||
dnl log2 could be used to improve the log function, however it requires C99. The check for log2 should be turned on,
|
||||
dnl as soon as we support C99.
|
||||
AC_CHECK_FUNCS(getcwd getwd asinh acosh atanh log1p hypot glob strfmon nice fpclass mempcpy strpncpy)
|
||||
AC_FUNC_FNMATCH
|
||||
AC_FUNC_FNMATCH
|
||||
|
||||
dnl
|
||||
dnl Check if there is a support means of creating a new process
|
||||
@ -490,7 +490,7 @@ PHP_NEW_EXTENSION(standard, array.c base64.c basic_functions.c browscap.c crc32.
|
||||
http_fopen_wrapper.c php_fopen_wrapper.c credits.c css.c \
|
||||
var_unserializer.c ftok.c sha1.c user_filters.c uuencode.c \
|
||||
filters.c proc_open.c streamsfuncs.c http.c password.c \
|
||||
random.c net.c,,,
|
||||
random.c net.c hrtime.c,,,
|
||||
-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
|
||||
|
||||
PHP_ADD_MAKEFILE_FRAGMENT
|
||||
|
@ -36,12 +36,11 @@ EXTENSION("standard", "array.c base64.c basic_functions.c browscap.c \
|
||||
url_scanner_ex.c ftp_fopen_wrapper.c http_fopen_wrapper.c \
|
||||
php_fopen_wrapper.c credits.c css.c var_unserializer.c ftok.c sha1.c \
|
||||
user_filters.c uuencode.c filters.c proc_open.c password.c \
|
||||
streamsfuncs.c http.c flock_compat.c random.c", false /* never shared */,
|
||||
streamsfuncs.c http.c flock_compat.c random.c hrtime.c", false /* never shared */,
|
||||
'/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
|
||||
PHP_INSTALL_HEADERS("", "ext/standard");
|
||||
if (PHP_MBREGEX != "no") {
|
||||
CHECK_HEADER_ADD_INCLUDE("oniguruma.h", "CFLAGS_STANDARD", PHP_MBREGEX + ";ext\\mbstring\\oniguruma")
|
||||
CHECK_HEADER_ADD_INCLUDE("oniguruma.h", "CFLAGS_STANDARD", PHP_MBREGEX + ";ext\\mbstring\\oniguruma")
|
||||
}
|
||||
ADD_MAKEFILE_FRAGMENT();
|
||||
PHP_INSTALL_HEADERS("", "ext/standard");
|
||||
|
||||
|
206
ext/standard/hrtime.c
Normal file
206
ext/standard/hrtime.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2017 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Niklas Keller <kelunik@php.net> |
|
||||
| Author: Anatol Belski <ab@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "php.h"
|
||||
#include "hrtime.h"
|
||||
|
||||
/* {{{ */
|
||||
/* This file reuses code parts from the cross-platform timer library
|
||||
Public Domain - 2011 Mattias Jansson / Rampant Pixels */
|
||||
|
||||
#if PHP_HRTIME_PLATFORM_POSIX
|
||||
|
||||
# include <unistd.h>
|
||||
# include <time.h>
|
||||
# include <string.h>
|
||||
|
||||
#elif PHP_HRTIME_PLATFORM_WINDOWS
|
||||
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
|
||||
static double _timer_scale = .0;
|
||||
|
||||
#elif PHP_HRTIME_PLATFORM_APPLE
|
||||
|
||||
# include <mach/mach_time.h>
|
||||
# include <string.h>
|
||||
static mach_timebase_info_data_t _timerlib_info;
|
||||
|
||||
#elif PHP_HRTIME_PLATFORM_HPUX
|
||||
|
||||
# include <sys/time.h>
|
||||
|
||||
#elif PHP_HRTIME_PLATFORM_AIX
|
||||
|
||||
# include <sys/time.h>
|
||||
# include <sys/systemcfg.h>
|
||||
|
||||
#endif
|
||||
|
||||
#define NANO_IN_SEC 1000000000
|
||||
/* }}} */
|
||||
|
||||
static int _timer_init()
|
||||
{/*{{{*/
|
||||
#if PHP_HRTIME_PLATFORM_WINDOWS
|
||||
|
||||
LARGE_INTEGER tf = {0};
|
||||
if (!QueryPerformanceFrequency(&tf) || 0 == tf.QuadPart) {
|
||||
return -1;
|
||||
}
|
||||
_timer_scale = (double)NANO_IN_SEC / (php_hrtime_t)tf.QuadPart;
|
||||
|
||||
#elif PHP_HRTIME_PLATFORM_APPLE
|
||||
|
||||
if (mach_timebase_info(&_timerlib_info)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif PHP_HRTIME_PLATFORM_POSIX
|
||||
|
||||
#if !_POSIX_MONOTONIC_CLOCK
|
||||
#ifdef _SC_MONOTONIC_CLOCK
|
||||
if (0 >= sysconf(_SC_MONOTONIC_CLOCK)) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif PHP_HRTIME_PLATFORM_HPUX
|
||||
|
||||
/* pass */
|
||||
|
||||
#elif PHP_HRTIME_PLATFORM_AIX
|
||||
|
||||
/* pass */
|
||||
|
||||
#else
|
||||
/* Timer unavailable. */
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}/*}}}*/
|
||||
|
||||
/* {{{ */
|
||||
PHP_MINIT_FUNCTION(hrtime)
|
||||
{
|
||||
if (0 > _timer_init()) {
|
||||
php_error_docref(NULL, E_WARNING, "Failed to initialize high-resolution timer");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline php_hrtime_t _timer_current(void)
|
||||
{/*{{{*/
|
||||
#if PHP_HRTIME_PLATFORM_WINDOWS
|
||||
LARGE_INTEGER lt = {0};
|
||||
QueryPerformanceCounter(<);
|
||||
return (php_hrtime_t)((php_hrtime_t)lt.QuadPart * _timer_scale);
|
||||
#elif PHP_HRTIME_PLATFORM_APPLE
|
||||
return (php_hrtime_t)mach_absolute_time() * _timerlib_info.numer / _timerlib_info.denom;
|
||||
#elif PHP_HRTIME_PLATFORM_POSIX
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
|
||||
if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) {
|
||||
return ((php_hrtime_t) ts.tv_sec * (php_hrtime_t)NANO_IN_SEC) + ts.tv_nsec;
|
||||
}
|
||||
return 0;
|
||||
#elif PHP_HRTIME_PLATFORM_HPUX
|
||||
return (php_hrtime_t) gethrtime();
|
||||
#elif PHP_HRTIME_PLATFORM_AIX
|
||||
timebasestruct_t t;
|
||||
read_wall_time(&t, TIMEBASE_SZ);
|
||||
time_base_to_time(&t, TIMEBASE_SZ);
|
||||
return (php_hrtime_t) t.tb_high * (php_hrtime_t)NANO_IN_SEC + t.tb_low;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}/*}}}*/
|
||||
|
||||
#if ZEND_ENABLE_ZVAL_LONG64
|
||||
#define PHP_RETURN_HRTIME(t) RETURN_LONG((zend_long)t)
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
# define HRTIME_U64A(i, s, len) _ui64toa_s(i, s, len, 10)
|
||||
#else
|
||||
# define HRTIME_U64A(i, s, len) \
|
||||
do { \
|
||||
int st = snprintf(s, len, "%llu", i); \
|
||||
s[st] = '\0'; \
|
||||
} while (0)
|
||||
#endif
|
||||
#define PHP_RETURN_HRTIME(t) do { \
|
||||
char _a[ZEND_LTOA_BUF_LEN]; \
|
||||
double _d; \
|
||||
HRTIME_U64A(t, _a, ZEND_LTOA_BUF_LEN); \
|
||||
_d = zend_strtod(_a, NULL); \
|
||||
RETURN_DOUBLE(_d); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* {{{ proto mixed hrtime([bool get_as_number = false])
|
||||
Returns an array of integers in form [seconds, nanoseconds] counted
|
||||
from an arbitrary point in time. If an optional boolean argument is
|
||||
passed, returns an integer on 64-bit platforms or float on 32-bit
|
||||
containing the current high-resolution time in nanoseconds. The
|
||||
delivered timestamp is monotonic and can not be adjusted. */
|
||||
PHP_FUNCTION(hrtime)
|
||||
{
|
||||
#if HRTIME_AVAILABLE
|
||||
zend_bool get_as_num = 0;
|
||||
php_hrtime_t t = _timer_current();
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(0, 1)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_BOOL(get_as_num)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (UNEXPECTED(get_as_num)) {
|
||||
PHP_RETURN_HRTIME(t);
|
||||
} else {
|
||||
array_init_size(return_value, 2);
|
||||
zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
|
||||
add_next_index_long(return_value, (zend_long)(t / (php_hrtime_t)NANO_IN_SEC));
|
||||
add_next_index_long(return_value, (zend_long)(t % (php_hrtime_t)NANO_IN_SEC));
|
||||
}
|
||||
#else
|
||||
RETURN_FALSE
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHPAPI php_hrtime_t php_hrtime_current(void)
|
||||
{/*{{{*/
|
||||
return _timer_current();
|
||||
}/*}}}*/
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: sw=4 ts=4 fdm=marker
|
||||
* vim<600: sw=4 ts=4
|
||||
*/
|
||||
|
58
ext/standard/hrtime.h
Normal file
58
ext/standard/hrtime.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 7 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2017 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Niklas Keller <kelunik@php.net> |
|
||||
| Author: Anatol Belski <ab@php.net> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef HRTIME_H
|
||||
#define HRTIME_H
|
||||
|
||||
#define PHP_HRTIME_PLATFORM_POSIX 0
|
||||
#define PHP_HRTIME_PLATFORM_WINDOWS 0
|
||||
#define PHP_HRTIME_PLATFORM_APPLE 0
|
||||
#define PHP_HRTIME_PLATFORM_HPUX 0
|
||||
#define PHP_HRTIME_PLATFORM_AIX 0
|
||||
|
||||
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
|
||||
# undef PHP_HRTIME_PLATFORM_POSIX
|
||||
# define PHP_HRTIME_PLATFORM_POSIX 1
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
# undef PHP_HRTIME_PLATFORM_WINDOWS
|
||||
# define PHP_HRTIME_PLATFORM_WINDOWS 1
|
||||
#elif defined(__APPLE__)
|
||||
# undef PHP_HRTIME_PLATFORM_APPLE
|
||||
# define PHP_HRTIME_PLATFORM_APPLE 1
|
||||
#elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
|
||||
# undef PHP_HRTIME_PLATFORM_HPUX
|
||||
# define PHP_HRTIME_PLATFORM_HPUX 1
|
||||
#elif defined(_AIX)
|
||||
# undef PHP_HRTIME_PLATFORM_AIX
|
||||
# define PHP_HRTIME_PLATFORM_AIX 1
|
||||
#endif
|
||||
|
||||
#define HRTIME_AVAILABLE (PHP_HRTIME_PLATFORM_POSIX || PHP_HRTIME_PLATFORM_WINDOWS || PHP_HRTIME_PLATFORM_APPLE || PHP_HRTIME_PLATFORM_HPUX || PHP_HRTIME_PLATFORM_AIX)
|
||||
|
||||
typedef uint64_t php_hrtime_t;
|
||||
|
||||
PHPAPI php_hrtime_t php_hrtime_current(void);
|
||||
|
||||
PHP_MINIT_FUNCTION(hrtime);
|
||||
|
||||
PHP_FUNCTION(hrtime);
|
||||
|
||||
#endif /* HRTIME_H */
|
@ -27,6 +27,7 @@
|
||||
#include "php_mail.h"
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "hrtime.h"
|
||||
#include "html.h"
|
||||
#include "exec.h"
|
||||
#include "file.h"
|
||||
|
26
ext/standard/tests/hrtime/hrtime.phpt
Normal file
26
ext/standard/tests/hrtime/hrtime.phpt
Normal file
@ -0,0 +1,26 @@
|
||||
--TEST--
|
||||
Test hrtime() aligns with microtime()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$m0 = microtime(true);
|
||||
$h0 = hrtime(true);
|
||||
for ($i = 0; $i < 1024*1024; $i++);
|
||||
$h1 = hrtime(true);
|
||||
$m1 = microtime(true);
|
||||
|
||||
$d0 = ($m1 - $m0)*1000000000.0;
|
||||
$d1 = $h1 - $h0;
|
||||
|
||||
/* Relative uncertainty. */
|
||||
$d = abs($d0 - $d1)/$d1;
|
||||
|
||||
if ($d > 0.05) {
|
||||
print "FAIL, $d";
|
||||
} else {
|
||||
print "OK, $d";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
OK, %f
|
15
ext/standard/tests/hrtime/hrtime_array.phpt
Normal file
15
ext/standard/tests/hrtime/hrtime_array.phpt
Normal file
@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Test hrtime() return array
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(hrtime());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
int(%d)
|
||||
[1]=>
|
||||
int(%d)
|
||||
}
|
Loading…
Reference in New Issue
Block a user