Mon Jul 17 14:10:08 2017 UTC ()
Performance fix for uniqid()

PHP uniqid() relies on microsecond-precise system clock to produce an
unique identifier. In order to avoid  using the same value, it first
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 microscecond change. 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.

Submitted upstream as https://bugs.php.net/bug.php?id=74851


(manu)
diff -r1.23 -r1.24 pkgsrc/lang/php71/distinfo
diff -r0 -r1.1 pkgsrc/lang/php71/patches/patch-ext_standard_uniqid.c

cvs diff -r1.23 -r1.24 pkgsrc/lang/php71/Attic/distinfo (expand / switch to unified diff)

--- pkgsrc/lang/php71/Attic/distinfo 2017/07/07 03:12:22 1.23
+++ pkgsrc/lang/php71/Attic/distinfo 2017/07/17 14:10:08 1.24
@@ -1,28 +1,29 @@ @@ -1,28 +1,29 @@
1$NetBSD: distinfo,v 1.23 2017/07/07 03:12:22 taca Exp $ 1$NetBSD: distinfo,v 1.24 2017/07/17 14:10:08 manu Exp $
2 2
3SHA1 (php-7.1.7.tar.bz2) = 1d7112102e79b052ebc47e3fd90ad24ddcfb8394 3SHA1 (php-7.1.7.tar.bz2) = 1d7112102e79b052ebc47e3fd90ad24ddcfb8394
4RMD160 (php-7.1.7.tar.bz2) = bcba338427733569b3be8ed27c5dba2afc3fca80 4RMD160 (php-7.1.7.tar.bz2) = bcba338427733569b3be8ed27c5dba2afc3fca80
5SHA512 (php-7.1.7.tar.bz2) = a505f8d1e140edff3f5bf6407adecf07cba1223fc905a978249684e9106832bcac0e9879ed07eed271c3bccd8204823d0e5ce2712dcb4432f50a3cf026e7bc84 5SHA512 (php-7.1.7.tar.bz2) = a505f8d1e140edff3f5bf6407adecf07cba1223fc905a978249684e9106832bcac0e9879ed07eed271c3bccd8204823d0e5ce2712dcb4432f50a3cf026e7bc84
6Size (php-7.1.7.tar.bz2) = 15751686 bytes 6Size (php-7.1.7.tar.bz2) = 15751686 bytes
7SHA1 (patch-acinclude.m4) = b682280fd89950c082c2226bdb7364b0dc475bad 7SHA1 (patch-acinclude.m4) = b682280fd89950c082c2226bdb7364b0dc475bad
8SHA1 (patch-configure) = a129e19ef87338f6e53ccc967c40ddcde7c7357c 8SHA1 (patch-configure) = a129e19ef87338f6e53ccc967c40ddcde7c7357c
9SHA1 (patch-ext_gd_config.m4) = 93b62daad93b9ee6dc28e06016f739bc26b0dc9f 9SHA1 (patch-ext_gd_config.m4) = 93b62daad93b9ee6dc28e06016f739bc26b0dc9f
10SHA1 (patch-ext_imap_config.m4) = f4e10ab81697b72019313f63bc630627a08efd92 10SHA1 (patch-ext_imap_config.m4) = f4e10ab81697b72019313f63bc630627a08efd92
11SHA1 (patch-ext_intl_config.m4) = 1ea3d3e6f05d5fed0bd4ca4518440199aec0954d 11SHA1 (patch-ext_intl_config.m4) = 1ea3d3e6f05d5fed0bd4ca4518440199aec0954d
12SHA1 (patch-ext_pcre_pcrelib_config.h) = c5fba95856628f68639fe63feeef04a5f83d3916 12SHA1 (patch-ext_pcre_pcrelib_config.h) = c5fba95856628f68639fe63feeef04a5f83d3916
13SHA1 (patch-ext_pdo__mysql_config.m4) = b1ef91be5a729040197e9af50da0f5fd1f6c90a8 13SHA1 (patch-ext_pdo__mysql_config.m4) = b1ef91be5a729040197e9af50da0f5fd1f6c90a8
14SHA1 (patch-ext_pdo_config.m4) = 522281775cc0e70a135b1f813158988ef1f3e244 14SHA1 (patch-ext_pdo_config.m4) = 522281775cc0e70a135b1f813158988ef1f3e244
15SHA1 (patch-ext_phar_Makefile.frag) = 558869b60f8ed6674a3ba1d595a65f010df4c426 15SHA1 (patch-ext_phar_Makefile.frag) = 558869b60f8ed6674a3ba1d595a65f010df4c426
16SHA1 (patch-ext_phar_phar_phar.php) = f630e3946b21b76d4fe857a43e00e25c9445f2c8 16SHA1 (patch-ext_phar_phar_phar.php) = f630e3946b21b76d4fe857a43e00e25c9445f2c8
17SHA1 (patch-ext_recode_recode.c) = a97a1815d6a41410f68c289debbb9396128a2159 17SHA1 (patch-ext_recode_recode.c) = a97a1815d6a41410f68c289debbb9396128a2159
18SHA1 (patch-ext_sqlite3_libsqlite_sqlite3.c) = 8a529a1b3f7c97731f2e719d006f67c3a7259bb5 18SHA1 (patch-ext_sqlite3_libsqlite_sqlite3.c) = 8a529a1b3f7c97731f2e719d006f67c3a7259bb5
19SHA1 (patch-ext_standard_basic__functions.c) = f97a2748c7b15fbd9a2d3c21e56079088cc05d56 19SHA1 (patch-ext_standard_basic__functions.c) = f97a2748c7b15fbd9a2d3c21e56079088cc05d56
 20SHA1 (patch-ext_standard_uniqid.c) = feefb8c6e601dee690d2ae99443e285136ef7224
20SHA1 (patch-ext_xsl_php__xsl.h) = a9877bff7bacc77926a4541a0ac171c00ad1a627 21SHA1 (patch-ext_xsl_php__xsl.h) = a9877bff7bacc77926a4541a0ac171c00ad1a627
21SHA1 (patch-makedist) = 2ac0e0391c031c4fcf4993e2269cde4c6bfddfd5 22SHA1 (patch-makedist) = 2ac0e0391c031c4fcf4993e2269cde4c6bfddfd5
22SHA1 (patch-php.ini-development) = dd65962000ec06439fae3c9bf252fa46be4e33fd 23SHA1 (patch-php.ini-development) = dd65962000ec06439fae3c9bf252fa46be4e33fd
23SHA1 (patch-php.ini-production) = ae61dffedf574b688fe576b0b2af748b7a28cd89 24SHA1 (patch-php.ini-production) = ae61dffedf574b688fe576b0b2af748b7a28cd89
24SHA1 (patch-run-tests.php) = 86c4d3f03eb8e31b5a35820f426533c9478571fb 25SHA1 (patch-run-tests.php) = 86c4d3f03eb8e31b5a35820f426533c9478571fb
25SHA1 (patch-sapi_cgi_Makefile.frag) = 18769900f588ff81cc34474542afa1d65c070e65 26SHA1 (patch-sapi_cgi_Makefile.frag) = 18769900f588ff81cc34474542afa1d65c070e65
26SHA1 (patch-sapi_cli_Makefile.frag) = 1cd29d09042863acbf5330e406410fdcf75d06b3 27SHA1 (patch-sapi_cli_Makefile.frag) = 1cd29d09042863acbf5330e406410fdcf75d06b3
27SHA1 (patch-sapi_fpm_fpm_events_port.c) = 0f10fdb32fb7cab58e2abda49fb1fc658c410150 28SHA1 (patch-sapi_fpm_fpm_events_port.c) = 0f10fdb32fb7cab58e2abda49fb1fc658c410150
28SHA1 (patch-sapi_fpm_php-fpm.conf.in) = b3c4fd499cbfd2dffd9176abb54e298ea542a5d7 29SHA1 (patch-sapi_fpm_php-fpm.conf.in) = b3c4fd499cbfd2dffd9176abb54e298ea542a5d7

File Added: pkgsrc/lang/php71/patches/Attic/patch-ext_standard_uniqid.c
$NetBSD: patch-ext_standard_uniqid.c,v 1.1 2017/07/17 14:10:08 manu Exp $

PHP uniqid() relies on microsecond-precise system clock to produce an
unique identifier. In order to avoid  using the same value, it first
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 microscecond change. 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.

Submitted upstream as https://bugs.php.net/bug.php?id=74851

--- ext/standard/uniqid.c.orig	2017-06-07 10:09:31.000000000 +0200
+++ ext/standard/uniqid.c	2017-07-08 08:24:24.000000000 +0200
@@ -52,25 +52,31 @@
 	zend_string *uniqid;
 	int sec, usec;
 	size_t prefix_len = 0;
 	struct timeval tv;
+	static struct timeval prev_tv = { 0, 0 };
 
 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sb", &prefix, &prefix_len,
 							  &more_entropy)) {
 		return;
 	}
 
-#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);
 
 	/* The max value usec can have is 0xF423F, so we use only five hex