com php-src: Fixed bug #74851: Improve uniqid() performance: NEWS ext/standard/uniqid.c

From: Date: Wed, 19 Jul 2017 17:54:19 +0000
Subject: com php-src: Fixed bug #74851: Improve uniqid() performance: NEWS ext/standard/uniqid.c
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-98641@lists.php.net to get a copy of this message
Commit: d25049cc1b74ae445d6521997a421a7462f1ad5b Author: Emmanuel Dreyfus <manu@netbsd.org> Wed, 19 Jul 2017 04:36:55 +0200 Committer: Nikita Popov <nikita.ppv@gmail.com> Wed, 19 Jul 2017 19:54:19 +0200 Parents: 6fcc7134f1d4aaf60e24202ed316c61636c5a95d Branches: PHP-7.2 master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=d25049cc1b74ae445d6521997a421a7462f1ad5b Log: Fixed bug #74851: Improve uniqid() performance uniqid() relies on microsecond-precise system clock to produce an unique identifier. In order to avoid using the same value, the original implementation calls usleep(1) to wait for the next microsecond. Unfortunately, usleep() specification says "The suspension time may be longer than requested due to the scheduling of other activity by the system." Indeed, the pause may as as long as an entire execution slice, causing a uniqid() call to last more than 10 ms. This is fixed by replacing the usleep() call by time polling using gettimeofday() until the microsecond changes. Since the getttimeoday() system call lasts around a microsecond, only a small time is wasted calling multiple gettimeofday. On the benefit side, uniqid() performance in increased 10000 fold without changing its behavior. Bugs: https://bugs.php.net/74851 Changed paths: M NEWS M ext/standard/uniqid.c Diff: diff --git a/NEWS b/NEWS index 7ef1302..a1a9b4e 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,10 @@ PHP NEWS - SPL: . Fixed bug #74669 (Unserialize ArrayIterator broken). (Andrew Nester) +- Standard: + .. Fixed bug #74851 (uniqid() without more_entropy performs badly). + (Emmanuel Dreyfus) + 20 Jul 2017, PHP 7.2.0beta1 - Core: diff --git a/ext/standard/uniqid.c b/ext/standard/uniqid.c index 22173ae..e8f2f19 100644 --- a/ext/standard/uniqid.c +++ b/ext/standard/uniqid.c @@ -38,17 +38,15 @@ #include "php_lcg.h" #include "uniqid.h" +#ifdef HAVE_GETTIMEOFDAY +ZEND_TLS struct timeval prev_tv = { 0, 0 }; + /* {{{ proto string uniqid([string prefix [, bool more_entropy]]) Generates a unique ID */ -#ifdef HAVE_GETTIMEOFDAY PHP_FUNCTION(uniqid) { char *prefix = ""; -#if defined(__CYGWIN__) - zend_bool more_entropy = 1; -#else zend_bool more_entropy = 0; -#endif zend_string *uniqid; int sec, usec; size_t prefix_len = 0; @@ -60,17 +58,20 @@ PHP_FUNCTION(uniqid) Z_PARAM_BOOL(more_entropy) ZEND_PARSE_PARAMETERS_END(); -#if HAVE_USLEEP && !defined(PHP_WIN32) if (!more_entropy) { -#if defined(__CYGWIN__) - php_error_docref(NULL, E_WARNING, "You must use 'more entropy' under CYGWIN"); - RETURN_FALSE; -#else - usleep(1); -#endif + /* This implementation needs current microsecond to change, + * hence we poll time until it does. This is much faster than + * calling usleep(1) which may cause the kernel to schedule + * another process, causing a pause of around 10ms. + */ + do { + (void)gettimeofday((struct timeval *) &tv, (struct timezone *) NULL); + } while (tv.tv_sec == prev_tv.tv_sec && tv.tv_usec == prev_tv.tv_usec); + + prev_tv.tv_sec = tv.tv_sec; + prev_tv.tv_usec = tv.tv_usec; } -#endif - gettimeofday((struct timeval *) &tv, (struct timezone *) NULL); + sec = (int) tv.tv_sec; usec = (int) (tv.tv_usec % 0x100000);

« previous php.cvs (#98641) next »