Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions EXTENSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,12 @@ MAINTENANCE: Maintained
STATUS: Working
SINCE: 8.5.0
-------------------------------------------------------------------------------
EXTENSION: uuid
PRIMARY MAINTAINER Máté Kocsis <kocsismate@php.net> (2026 - 2026)
MAINTENANCE: Maintained
STATUS: Working
SINCE: 8.6.0
-------------------------------------------------------------------------------
EXTENSION: zip
PRIMARY MAINTAINER: Pierre-Alain Joye <pajoye@php.net> (2006 - 2011)
Remi Collet <remi@php.net> (2013-2020)
Expand Down
1 change: 1 addition & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ PHP 8.6 INTERNALS UPGRADE NOTES
ZEND_AST_TRAIT_METHOD_REFERENCE.
. The EMPTY_SWITCH_DEFAULT_CASE() macro has been removed. Use
default: ZEND_UNREACHABLE(); instead.
. Introduced a new time-retrieval API zend_time_*.

========================
2. Build system changes
Expand Down
55 changes: 55 additions & 0 deletions Zend/zend_time.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Marc Bennewitz <marc@mabe.berlin> |
+----------------------------------------------------------------------+
*/

#include "zend_time.h"

/* Current real/wall-time in seconds */
ZEND_API time_t zend_time_real_sec(void) {
return time(NULL);
}

ZEND_API void zend_time_real_spec(struct timespec *ts) {
#if defined(HAVE_CLOCK_GETTIME)

(void) clock_gettime(CLOCK_REALTIME, ts);

#elif defined(HAVE_TIMESPEC_GET)

(void) timespec_get(ts, TIME_UTC);

#elif defined(HAVE_GETTIMEOFDAY)

struct timeval tv;
(void) gettimeofday(&tv, NULL);
zend_time_val2spec(tv, ts);

#else

ts->tv_sec = zend_time_real_get();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ts->tv_sec = zend_time_real_get();
ts->tv_sec = zend_time_real_sec();

Is this a typo? We don't get a definition of zend_time_real_get yet(?)

ts->tv_nsec = 0;

#endif
}

ZEND_API uint64_t zend_time_mono_fallback_nsec(void) {
#if ZEND_HRTIME_AVAILABLE
return (uint64_t)zend_hrtime();
#else
struct timespec ts;
zend_time_real_spec(&ts);
return ((uint64_t) ts.tv_sec * ZEND_NANO_IN_SEC) + ts.tv_nsec;
#endif
}
95 changes: 95 additions & 0 deletions Zend/zend_time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Marc Bennewitz <marc@mabe.berlin> |
+----------------------------------------------------------------------+
*/

#ifndef ZEND_TIME_H
#define ZEND_TIME_H

#include "zend_portability.h"

#ifdef PHP_WIN32
# include "win32/time.h"
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <time.h>

#include "zend_hrtime.h"

#ifndef PHP_WIN32
# define tv_sec_t time_t
# define tv_usec_t suseconds_t
#else
# define tv_sec_t long
# define tv_usec_t long
#endif

#define ZEND_MILLI_IN_SEC 1000U
#define ZEND_MICRO_IN_SEC 1000000U

BEGIN_EXTERN_C()

/* Assign seconds to timeval */
static zend_always_inline void zend_time_sec2val(time_t s, struct timeval *tv) {
tv->tv_sec = (tv_sec_t) s;
tv->tv_usec = 0;
}

/* Assign microseconds to timeval */
static zend_always_inline void zend_time_usec2val(int64_t usec, struct timeval *tv) {
tv->tv_sec = (tv_sec_t) (usec / ZEND_MICRO_IN_SEC);
tv->tv_usec = (tv_usec_t) (usec % ZEND_MICRO_IN_SEC);

if (UNEXPECTED(tv->tv_usec < 0)) {
tv->tv_usec += ZEND_MICRO_IN_SEC;
tv->tv_sec -= 1;
}
}

/* Assign double (seconds) to timeval */
static zend_always_inline void zend_time_dbl2val(double s, struct timeval *tv) {
tv->tv_sec = (tv_sec_t) s;
tv->tv_usec = (tv_usec_t) ((s - tv->tv_sec) * ZEND_MICRO_IN_SEC);

if (UNEXPECTED(tv->tv_usec < 0)) {
tv->tv_usec += ZEND_MICRO_IN_SEC;
tv->tv_sec -= 1;
} else if (UNEXPECTED(tv->tv_usec >= ZEND_MICRO_IN_SEC)) {
// rare, but protects against rounding up to exactly 1 second
tv->tv_usec -= ZEND_MICRO_IN_SEC;
tv->tv_sec += 1;
}
}

/* Assign timeval to timespec */
static zend_always_inline void zend_time_val2spec(struct timeval tv, struct timespec *ts) {
ts->tv_sec = (time_t) tv.tv_sec;
ts->tv_nsec = (long) (tv.tv_usec * 1000);
}

/* Current real/wall-time in seconds */
ZEND_API time_t zend_time_real_sec(void);

/* Current real/wall-time in up-to nano seconds */
ZEND_API void zend_time_real_spec(struct timespec *ts);

/* Monotonic time in nanoseconds with a fallback to real/wall-time
if no monotonic timer is available */
ZEND_API uint64_t zend_time_mono_fallback_nsec(void);

END_EXTERN_C()

#endif // ZEND_TIME_H
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ AC_CHECK_FUNCS(m4_normalize([
asctime_r
asprintf
chroot
clock_gettime
ctime_r
explicit_memset
fdatasync
Expand Down Expand Up @@ -598,6 +599,7 @@ AC_CHECK_FUNCS(m4_normalize([
strptime
strtok_r
symlink
timespec_get
tzset
unsetenv
usleep
Expand Down Expand Up @@ -1754,6 +1756,7 @@ PHP_ADD_SOURCES([Zend], m4_normalize([
zend_generators.c
zend_hash.c
zend_highlight.c
zend_time.c
zend_hrtime.c
zend_inheritance.c
zend_ini_parser.c
Expand Down
1 change: 1 addition & 0 deletions ext/standard/credits_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ CREDIT_LINE("System V Shared Memory", "Christian Cartus");
CREDIT_LINE("tidy", "John Coggeshall, Ilia Alshanetsky");
CREDIT_LINE("tokenizer", "Andrei Zmievski, Johannes Schlueter");
CREDIT_LINE("uri", "Máté Kocsis, Tim Düsterhus, Ignace Nyamagana Butera, Arnaud Le Blanc, Dennis Snell, Niels Dossche, Nicolas Grekas");
CREDIT_LINE("uuid", "Máté Kocsis");
CREDIT_LINE("XML", "Stig Bakken, Thies C. Arntzen, Sterling Hughes");
CREDIT_LINE("XMLReader", "Rob Richards");
CREDIT_LINE("XMLWriter", "Rob Richards, Pierre-Alain Joye");
Expand Down
2 changes: 2 additions & 0 deletions ext/uuid/CREDITS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uuid
Máté Kocsis
7 changes: 7 additions & 0 deletions ext/uuid/benchmark/7_php_uuid.expectation
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
X-Powered-By: PHP/%v
Content-type: text/html; charset=UTF-8

object(Uuid\UuidV7)#%d (%d) {
["uuid"]=>
string(36) "%s-%s-%s-%s-%s"
}
8 changes: 8 additions & 0 deletions ext/uuid/benchmark/7_php_uuid.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
TEST_NAME="PHP UUID"
TEST_ID=php_uuid
TEST_WARMUP=20
TEST_ITERATIONS=50
TEST_REQUESTS=10

TEST_TYPE=micro
TEST_FILE=config/test/7_php_uuid.php
7 changes: 7 additions & 0 deletions ext/uuid/benchmark/7_php_uuid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

for ($i = 0; $i < 50_000; $i++) {
$uuid = Uuid\UuidV7::generate();
}

var_dump($uuid);
7 changes: 7 additions & 0 deletions ext/uuid/benchmark/8_symfony_uuid.expectation
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
X-Powered-By: PHP/%v
Content-type: text/html; charset=UTF-8

object(Symfony\Component\Uid\UuidV7)#%d (%d) {
["uid":protected]=>
string(36) "%s-%s-%s-%s-%s"
}
8 changes: 8 additions & 0 deletions ext/uuid/benchmark/8_symfony_uuid.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
TEST_NAME="Symfony UUID"
TEST_ID=symfony_uuid
TEST_WARMUP=20
TEST_ITERATIONS=50
TEST_REQUESTS=10

TEST_TYPE=micro
TEST_FILE=config/test/8_symfony_uuid.php
9 changes: 9 additions & 0 deletions ext/uuid/benchmark/8_symfony_uuid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

require_once __DIR__ . "/../../app/symfony_uuid/vendor/autoload.php";

for ($i = 0; $i < 50_000; $i++) {
$uuid = new Symfony\Component\Uid\UuidV7();
}

var_dump($uuid);
22 changes: 22 additions & 0 deletions ext/uuid/benchmark/8_symfony_uuid_install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -e

symfony_version="8.0.8"
symfony_dir="$PROJECT_ROOT/app/symfony_uuid"

if [[ -d "$symfony_dir" ]]; then
echo "symfony/uid is already installed"
exit
fi

mkdir -p "$symfony_dir"

sudo docker run --rm \
--volume $PROJECT_ROOT:/code \
--user $(id -u):$(id -g) \
setup bash -c "\
set -e \
[[ -n '$GITHUB_TOKEN' ]] && composer config --global github-oauth.github.com '$GITHUB_TOKEN'; \
composer require symfony/uid:$symfony_version --ignore-platform-reqs --no-interaction --working-dir=/code/app/symfony_uuid && \
composer config platform-check false --working-dir=/code/app/symfony_uuid && \
composer dump-autoload --classmap-authoritative --no-interaction --working-dir=/code/app/symfony_uuid"
9 changes: 9 additions & 0 deletions ext/uuid/benchmark/9_ramsey_uuid.expectation
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
X-Powered-By: PHP/%v
Content-type: text/html; charset=UTF-8

object(Ramsey\Uuid\Lazy\LazyUuidFromString)#%d (%d) {
["unwrapped":"Ramsey\Uuid\Lazy\LazyUuidFromString":private]=>
NULL
["uuid":"Ramsey\Uuid\Lazy\LazyUuidFromString":private]=>
string(36) "%s-%s-%s-%s-%s"
}
8 changes: 8 additions & 0 deletions ext/uuid/benchmark/9_ramsey_uuid.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
TEST_NAME="Ramsey UUID"
TEST_ID=ramsey_uuid
TEST_WARMUP=20
TEST_ITERATIONS=50
TEST_REQUESTS=10

TEST_TYPE=micro
TEST_FILE=config/test/9_ramsey_uuid.php
9 changes: 9 additions & 0 deletions ext/uuid/benchmark/9_ramsey_uuid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

require_once __DIR__ . "/../../app/ramsey_uuid/vendor/autoload.php";

for ($i = 0; $i < 50_000; $i++) {
$uuid = Ramsey\Uuid\Uuid::uuid7();
}

var_dump($uuid);
22 changes: 22 additions & 0 deletions ext/uuid/benchmark/9_ramsey_uuid_install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -e

ramsey_version="4.9.2"
ramsey_dir="$PROJECT_ROOT/app/ramsey_uuid"

if [[ -d "$ramsey_dir" ]]; then
echo "ramsey/uuid is already installed"
exit
fi

mkdir -p "$ramsey_dir"

sudo docker run --rm \
--volume $PROJECT_ROOT:/code \
--user $(id -u):$(id -g) \
setup bash -c "\
set -e \
[[ -n '$GITHUB_TOKEN' ]] && composer config --global github-oauth.github.com '$GITHUB_TOKEN'; \
composer require ramsey/uuid:$ramsey_version --ignore-platform-reqs --no-interaction --working-dir=/code/app/ramsey_uuid && \
composer config platform-check false --working-dir=/code/app/ramsey_uuid && \
composer dump-autoload --classmap-authoritative --no-interaction --working-dir=/code/app/ramsey_uuid"
11 changes: 11 additions & 0 deletions ext/uuid/config.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
dnl Configure options
dnl

PHP_INSTALL_HEADERS([ext/uuid], m4_normalize([
php_uuid.h
uuidv7-h/php_uuid.h
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be uuidv7.h right?

Suggested change
uuidv7-h/php_uuid.h
uuidv7-h/uuidv7.h

]))

PHP_NEW_EXTENSION(uuid, [php_uuid.c], [no],,[-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
PHP_ADD_EXTENSION_DEP(uuid, date)
PHP_ADD_EXTENSION_DEP(uuid, random)
7 changes: 7 additions & 0 deletions ext/uuid/config.w32
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
EXTENSION("uuid", "php_uuid.c", false /* never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");

ADD_FLAG("CFLAGS_UUID", "/D UUID_STATIC_BUILD");

ADD_EXTENSION_DEP("uuid", "date");
ADD_EXTENSION_DEP("uuid", "random");
PHP_INSTALL_HEADERS("ext/uuid", "php_uuid.h uuidv7-h/uuidv7.h");
Loading
Loading