-
Notifications
You must be signed in to change notification settings - Fork 8k
Implement hrtime() #2368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement hrtime() #2368
Changes from all commits
43baee0
9d37a59
009dcd4
2590c10
9ff8512
14c9aca
2b32f68
fe0bd6e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
|
@@ -455,7 +455,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,,, | ||
| random.c hrtime.c,,, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should check for symbols and mark a fallback case, maybe falling back to gettimeofday() or anything better in the code. Specifically for POSIX - it should check for CLOCK_MONOTONIC define, as there can be variations in the implementations. I think, it's even better to check for different platforms explicitly - BSD, Solaris for sure, and maybe some other.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I know,
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At least one platform doesn't have it, as per the linked blog. Edge cases, still they should be covered them if they're known.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes,
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added support for HP-UX just now. Any other edge cases we know of? I think the checks should be fine now with the conditional definition?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, i thought we'd rather exclude it in configure, but works this way, too. Except probably only a few can test it :/ There are no cases, i'd be aware of otherwise.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is not a so-easy subject to takle. Systems tend to be pretty different in their API for time measurement.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jpauli That's talking about CPU time for benchmarking, that's not the use case I have. While benchmarking is another possible use case for |
||
| -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) | ||
|
|
||
| PHP_ADD_MAKEFILE_FRAGMENT | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| /* | ||
| +----------------------------------------------------------------------+ | ||
| | 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> | | ||
| +----------------------------------------------------------------------+ | ||
| */ | ||
|
|
||
| /* $Id$ */ | ||
|
|
||
| #include "php.h" | ||
| #include "zend_exceptions.h" | ||
| #include "hrtime.h" | ||
|
|
||
| #if HRTIME_AVAILABLE | ||
|
|
||
| /* - timer.h ------------------------------------------------------------------------------------ */ | ||
| /* The following code is based on: | ||
| timer.h - Cross-platform timer library - Public Domain - 2011 Mattias Jansson / Rampant Pixels */ | ||
|
|
||
| #define TIMER_PLATFORM_POSIX 0 | ||
| #define TIMER_PLATFORM_WINDOWS 0 | ||
| #define TIMER_PLATFORM_APPLE 0 | ||
| #define TIMER_PLATFORM_HPUX 0 | ||
|
|
||
| #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) && defined(CLOCK_MONOTONIC) | ||
|
|
||
| # undef TIMER_PLATFORM_POSIX | ||
| # define TIMER_PLATFORM_POSIX 1 | ||
| # include <unistd.h> | ||
| # include <time.h> | ||
| # include <string.h> | ||
|
|
||
| #elif defined(_WIN32) || defined(_WIN64) | ||
|
|
||
| # undef TIMER_PLATFORM_WINDOWS | ||
| # define TIMER_PLATFORM_WINDOWS 1 | ||
| # define WIN32_LEAN_AND_MEAN | ||
| # include <windows.h> | ||
|
|
||
| #elif defined(__APPLE__) | ||
|
|
||
| # undef TIMER_PLATFORM_APPLE | ||
| # define TIMER_PLATFORM_APPLE 1 | ||
| # include <mach/mach_time.h> | ||
| # include <string.h> | ||
| static mach_timebase_info_data_t _timerlib_info; | ||
| static void absolutetime_to_nanoseconds (uint64_t mach_time, uint64_t* clock ) { *clock = mach_time * _timerlib_info.numer / _timerlib_info.denom; } | ||
|
|
||
| #elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__))) | ||
|
|
||
| # undef TIMER_PLATFORM_HPUX | ||
| # define TIMER_PLATFORM_HPUX 1 | ||
| # include <sys/time.h> | ||
|
|
||
| #endif | ||
|
|
||
| static uint64_t _timer_freq = 0; | ||
|
|
||
| static int _timer_init() | ||
| { | ||
| #if TIMER_PLATFORM_WINDOWS | ||
|
|
||
| uint64_t unused; | ||
| if (!QueryPerformanceFrequency((LARGE_INTEGER*) &_timer_freq) || | ||
| !QueryPerformanceCounter((LARGE_INTEGER*) &unused)) { | ||
| return -1; | ||
| } | ||
|
|
||
| #elif TIMER_PLATFORM_APPLE | ||
|
|
||
| if (mach_timebase_info(&_timerlib_info)) { | ||
| return -1; | ||
| } | ||
| _timer_freq = 1000000000ULL; | ||
|
|
||
| #elif TIMER_PLATFORM_POSIX | ||
|
|
||
| struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; | ||
| if (clock_gettime(CLOCK_MONOTONIC, &ts)) { | ||
| return -1; | ||
| } | ||
| _timer_freq = 1000000000ULL; | ||
|
|
||
| #elif TIMER_PLATFORM_HPUX | ||
|
|
||
| _timer_freq = 1000000000ULL; | ||
|
|
||
| #endif | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static uint64_t _timer_current() | ||
| { | ||
| #if TIMER_PLATFORM_WINDOWS | ||
|
|
||
| uint64_t curclock; | ||
| QueryPerformanceCounter((LARGE_INTEGER*) &curclock); | ||
| return curclock; | ||
|
|
||
| #elif TIMER_PLATFORM_APPLE | ||
|
|
||
| uint64_t curclock = 0; | ||
| absolutetime_to_nanoseconds(mach_absolute_time(), &curclock); | ||
| return curclock; | ||
|
|
||
| #elif TIMER_PLATFORM_POSIX | ||
|
|
||
| struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; | ||
| if (clock_gettime(CLOCK_MONOTONIC, &ts)) { | ||
| return -1; | ||
| } | ||
| return ((uint64_t) ts.tv_sec * 1000000000ULL) + ts.tv_nsec; | ||
|
|
||
| #elif TIMER_PLATFORM_HPUX | ||
|
|
||
| return (uint64_t) gethrtime(); | ||
|
|
||
| #endif | ||
| } | ||
|
|
||
| /* - end of timer.h ----------------------------------------------------------------------------- */ | ||
|
|
||
| /* {{{ */ | ||
| PHP_MINIT_FUNCTION(hrtime) | ||
| { | ||
| if (_timer_init()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For whatever reason, if the initialization has failed, the whole should fallback to something.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fail back to what? Depends on what we want to guarantee for this function. If we want to guarantee no jumps and monotony, we can't fallback to anything.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we don't want to make the timer a hard requirement we can either a) only register the function is the functionality is available or b) throw an exception if the function is called.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thought was falling back to getttimeofday() or alike, as it is supposed to be a rare case, and otherwise it needs one more condition check. Fine with being strict and exception, it solves the case as well.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case we won't ever find the missing platforms and just think those are supported.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jpauli If it fails in
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was talking about the case where we would replacing a failing init call by a gettimeofday() call. In such a case, we must return SUCCESS, and throw a Notice.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no such case. If it can't use a monotonic time but compiled fine, it will result in a fatal error. It won't fall back to gettimeofday().
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I thought we were talking about a possible replacement by gtod() if failing , so we forget such an idea.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @weltling wanted to do that. I don't want to do that, as it breaks the guarantee of monotony and might jump, while |
||
| php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize internal timer"); | ||
| return FAILURE; | ||
| } | ||
|
|
||
| return SUCCESS; | ||
| } | ||
| /* }}} */ | ||
|
|
||
| /* {{{ */ | ||
| PHP_MSHUTDOWN_FUNCTION(hrtime) | ||
| { | ||
| return SUCCESS; | ||
| } | ||
| /* }}} */ | ||
|
|
||
| /* {{{ proto float hrtime() | ||
| Returns a float containing the current high-resolution time in seconds | ||
| counted from an arbitrary point in time */ | ||
| PHP_FUNCTION(hrtime) | ||
| { | ||
| if (zend_parse_parameters_none() == FAILURE) { | ||
| return; | ||
| } | ||
|
|
||
| uint64_t current_time = _timer_current(); | ||
|
|
||
| if (UNEXPECTED(current_time == -1)) { | ||
| zend_throw_exception(zend_ce_error, "Failed to get current system time", 0); | ||
| return; | ||
| } | ||
|
|
||
| RETURN_DOUBLE((double) current_time / _timer_freq); | ||
| } | ||
| /* }}} */ | ||
|
|
||
| #endif /* HRTIME_AVAILABLE */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* | ||
| +----------------------------------------------------------------------+ | ||
| | 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> | | ||
| +----------------------------------------------------------------------+ | ||
| */ | ||
|
|
||
| /* $Id$ */ | ||
|
|
||
| #ifndef HRTIME_H | ||
| #define HRTIME_H | ||
|
|
||
| #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) && defined(CLOCK_MONOTONIC) | ||
| #define HRTIME_AVAILABLE 1 | ||
| #elif defined(_WIN32) || defined(_WIN64) | ||
| #define HRTIME_AVAILABLE 1 | ||
| #elif defined(__APPLE__) | ||
| #define HRTIME_AVAILABLE 1 | ||
| #elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__))) | ||
| #define HRTIME_AVAILABLE 1 | ||
| #else | ||
| #define HRTIME_AVAILABLE 0 | ||
| #endif | ||
|
|
||
| #if HRTIME_AVAILABLE | ||
| PHP_MINIT_FUNCTION(hrtime); | ||
| PHP_MSHUTDOWN_FUNCTION(hrtime); | ||
|
|
||
| PHP_FUNCTION(hrtime); | ||
| #endif /* HRTIME_AVAILABLE */ | ||
|
|
||
| #endif /* HRTIME_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| --TEST-- | ||
| Test hrtime() aligns with microtime() | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| $hrtime = hrtime(); | ||
| $microtime = microtime(1); | ||
|
|
||
| usleep(500000); | ||
|
|
||
| $hrdiff = hrtime() - $hrtime; | ||
| $microdiff = microtime(1) - $microtime; | ||
|
|
||
| if (abs($hrdiff - $microdiff) > 0.0001) { | ||
| print "fail"; | ||
| } else { | ||
| print "OK"; | ||
| } | ||
|
|
||
| ?> | ||
| --EXPECT-- | ||
| OK |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| --TEST-- | ||
| Test hrtime() errors | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| hrtime(true); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Warning: hrtime() expects exactly 0 parameters, 1 given in %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revoke the WS change.