Req #74851 [Opn]: uniqid performances
| From: | nikic@php.net | Date: | Tue, 04 Jul 2017 23:25:05 +0000 |
| Subject: | Req #74851 [Opn]: uniqid performances | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-209812@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=74851&edit=1
ID: 74851
Updated by: nikic@php.net
Reported by: manu at netbsd dot org
Summary: uniqid performances
Status: Open
Type: Feature/Change Request
Package: Performance problem
Operating System: NetBSD
PHP Version: 7.1.6
Block user comment: N
Private report: N
New Comment:
This has been discussed a couple of times already and the argument is basically always the same:
We're don't want to change the uniqid output format for BC reasons. In particular changing
the length is problematic, as uniqid output is stored in length-limited database fields (for
example). Switching uniqid to use UUIDs would certainly cause breakage.
There is an active proposal to expose a UUID interface (without changing the uniqid function): https://wiki.php.net/rfc/uuid
I think what we should do here is deprecate uniqid() in favor of bin2hex(random_bytes(16)), or the
proposed UUID interface.
Previous Comments:
------------------------------------------------------------------------
[2017-07-04 23:01:13] manu at netbsd dot org
The internals discussion ends with the idea of returning an UUID, which is exactly what the provided
patch in this bug report does.
------------------------------------------------------------------------
[2017-07-04 21:38:13] cmb@php.net
Note, that there is already a related RFC[1] including a
discussion on internals[2].
[1] <https://wiki.php.net/rfc/uniqid>
[2] <http://marc.info/?t=147339817200002&r=1&w=2>
------------------------------------------------------------------------
[2017-07-04 03:19:50] manu at netbsd dot org
Description:
------------
uniqid() uses system microsecond-precise clock to produce an unique identifier. In order to avoid
producing the same value, it will always call usleep() to wait for the next microsecond.
The problem here is that usleep() may wait for much longer. According to Opengroup's POSIX,
"The suspension time may be longer than requested due to the scheduling of other activity by
the system". Indeed tests on NetBSD show that the kernel will schedule another process during
the usleep() call, resulting in a typical uniqid() duration around 16 ms, which is around 16000 time
slower than intended.
I suggest to address the problem by using uuidgen() system call if available. This system call is
not in POSIX standard, but will be available on most modern systems. The call costs around a
microsecond, and it produce a much better unique identifier than what uniqid() currently does.
Attached is a patch against PHP 7.1.6 that cause PHP's configure script to look up uuidgen(),
and that uses it in uniqid() if it is available.
The same problem was reported at lease in bugs #65626, #37106, #37840 and #14248, but with no
satisfying fix proposed, in my opinion.
Test script:
---------------
Test to compare uniqid() performance across systems:
time php -r 'for ($i = 0; $i < 1000; $i++) uniqid();'
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=74851&edit=1