We have been using UUID for years and different ways to generate UUID exist.
I prefer the PECL extension over the ramsey/uuid because it’s simpler and more straightforward. Few weeks ago, with Nicolas Grekas we had the idea to port the PECL to plain PHP as a Symfony Polyfill. Then, we wanted to blog about FFI, a new PHP 7.4 feature. With Baptiste Leduc, we bound the libuuid
to PHP.
So now, there are many ways to generate UUID in PHP, at least 4. Let's compare them:
- The PECL extension;
- A polyfill for the PECL extension;
- An abstraction layer on top of many generator + an UUID component: ramsey/uuid;
- A FFI binding for PHP 7.4+.
I created a benchmark to see how theses implementations compare:
+----------------------+---------+-------+
| subject | mean | diff |
+----------------------+---------+-------+
| benchPecl | 0.637μs | 1.00x |
| benchSymfonyPolyfill | 1.736μs | 2.72x |
| benchJoliCodeFFI | 1.349μs | 2.12x |
| benchRamsey | 4.295μs | 6.74x |
+----------------------+---------+-------+
+----------------------+---------+-------+
| subject | mean | diff |
+----------------------+---------+-------+
| benchPecl | 4.546μs | 2.87x |
| benchSymfonyPolyfill | 1.583μs | 1.00x |
| benchJoliCodeFFI | 5.416μs | 3.42x |
| benchRamsey | 2.103μs | 1.33x |
+----------------------+---------+-------+
UUID are composed in part - or totally - by pseudo-random data. Generating random data is something really hard for a computer and slow by design. You can read more on wikipedia about this topic.
V1 is time based. It means there are not so much random data. But each UUID must be unique, so an internal counter is required.
- The PECL is the fastest here because it uses some features of the kernel to get incremental data,
- The FFI binding is slower because there is a significant overhead with FFI for things that are really fast in the underlying library. This overhead comes from the conversion type between PHP and the underlying library,
- The Polyfill is slower because it must deal with the counter manually,
- The Rasmey implementation is the slowest because the way it deals with counter could be improved.
V4 is full of random data. It means it is really expensive for the CPU to generate one compared to a V1.
- The Polyfill is the fastest because it asks for a big amount of random data only once. Then it uses it to generate the UUID,
- The Rasmey implementation is also very fast for the same reason,
- The PECL is much slower due to the underlying library (
libuuid
) asking many pieces of random data (remember it's very slow by design) and then it assembles them, - The FFI binding is the slowest since it relies on the same
libuuid
library, and it adds the FFI overhead.
Now you now know everything about uuid, so… just make the right choice. ;)
Keep in mind that the FFI binding works only with PHP 7.4+, so it’s likely unusable for many projects (for now).
ramsey/uuid is an UUID component that leverage many uuid generator (it can use the PECL internally). It could be interesting to use the polyfill in the ramsey/uuid implementation.
And since the polyfill is the same thing than the PECL extension, the final choice is about the API:
something simple: the PECL (or the polyfill if you can’t install an extension), something more feature-rich: the ramsey/uuid component, something hype: the FFI binding
Now you know everything about the ways to generate UUID in PHP, just use the right one for you.