php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #74851
Patch 0001-uniqid-performance-fix.patch revision 2017-07-19 02:40 UTC by manu at netbsd dot org
Patch patch3-ext_standard_uniqid.c revision 2017-07-08 14:47 UTC by manu at netbsd dot org
Patch patch2-ext_standard_uniqid.c revision 2017-07-05 15:49 UTC by manu at netbsd dot org
Patch patch-ext_standard_uniqid.c revision 2017-07-04 03:20 UTC by manu at netbsd dot org

Patch 0001-uniqid-performance-fix.patch for Performance problem Bug #74851

Patch version 2017-07-19 02:40 UTC

Return to Bug #74851 | Download this patch
This patch renders other patches obsolete

Obsolete patches:

Patch Revisions:

Developer: manu@netbsd.org

From 39245b66d77b0130c2bcdcb021fab9effc5edf2d Mon Sep 17 00:00:00 2001
From: Emmanuel Dreyfus <manu@netbsd.org>
Date: Wed, 19 Jul 2017 04:36:55 +0200
Subject: [PATCH] uniqid() performance fix

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 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.
---
 ext/standard/uniqid.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/ext/standard/uniqid.c b/ext/standard/uniqid.c
index 22173ae01d..b3c4ca54e4 100644
--- a/ext/standard/uniqid.c
+++ b/ext/standard/uniqid.c
@@ -44,15 +44,12 @@
 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;
 	struct timeval tv;
+	ZEND_TLS struct timeval prev_tv = { 0, 0 };
 
 	ZEND_PARSE_PARAMETERS_START(0, 2)
 		Z_PARAM_OPTIONAL
@@ -60,17 +57,22 @@ 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);
 
-- 
2.11.0

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 16:01:27 2024 UTC