Bug #64188 [Opn->Nab]: strtotime is 7 times slower for dates that end with Z instead of UTC
| From: | cmb@php.net | Date: | Wed, 03 Feb 2021 13:25:29 +0000 |
| Subject: | Bug #64188 [Opn->Nab]: strtotime is 7 times slower for dates that end with Z instead of UTC | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-231913@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=64188&edit=1
ID: 64188
Updated by: cmb@php.net
Reported by: efbiaiinzinz at hotmail dot com
Summary: strtotime is 7 times slower for dates that end with
Z instead of UTC
-Status: Open
+Status: Not a bug
Type: Bug
Package: Performance problem
Operating System: Windows / Linux / All
PHP Version: 5.4.11
-Assigned To:
+Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
If this is still relevant, please report it upstream to
<https://github.com/derickr/timelib>.
Previous Comments:
------------------------------------------------------------------------
[2013-02-11 08:32:36] efbiaiinzinz at hotmail dot com
Description:
------------
According to the date rules seen at http://en.wikipedia.org/wiki/ISO_8601 a date
with ending Z should be considered UTC date.
UTC description also says that UTC date can be denoted with appending Z to the
end: http://en.wikipedia.org/wiki/Coordinated_Universal_Time
PHP codebase does follow those rules, but does so suboptimally.
We have a codebase that parses in big GPS files from different sport watches and
so far all bigger providers (garmin, polar, suunto) encode the time values in
those files as 2013-01-01T12:00:00Z or 2013-01-01T12:00:00.000Z.
We noticed that for bigger files the parsing times were quite bad and most time
was spent in strtotime so we started to experiment. Removing the Z part resulted
in fast strtotime but wrong result (date was assumed to be local not UTC). When
we tried to replace Z with UTC, parsing was correct and fast.
After looking at date parsing code in PHP 5.4.11 we noticed few things:
ext/date/lib/parse_date.c
const static timelib_tz_lookup_table* zone_search(const char *word, long
gmtoffset, int isdst)
...
if (strcasecmp("utc", word) == 0 || strcasecmp("gmt", word) == 0) {
return timelib_timezone_utc;
}
ext/date/lib/parse_date.c
static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int
*tz_not_found, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_wrapper)
...
/* If we have a TimeZone identifier to start with, use it */
if (strstr(tz_abbr, "/") || strcmp(tz_abbr, "UTC") == 0) {
ext/date/lib/parse_date.c
const static timelib_tz_lookup_table timelib_timezone_utc[] = {
{ "utc", 0, 0, "UTC" },
};
There are optimizations for cases when string contains UTC but no optimizations
for another official UTC format that ends with Z.
We tested on PHP 5.4.11 and 5.3.21 on a windows machin plus on our production
Linux server with PHP 5.3.20.
Test script:
---------------
<?php
ini_set('date.timezone', 'UTC');//make sure no warnings are shown
$br = isset($_SERVER['HTTP_USER_AGENT']) ? "<br />\r\n" :
"\r\n";
$times_z = $times_utc = array();
$time = time();
$counter = 50000;
for($i = 0; $i < $counter; $i++, $time++) {//Generate two arrays, one has datetimes that end with
Z and other has UTC endings
$date = date('Y-m-d\TH:i:s', $time);
$times_z []= $date . 'Z';
$times_utc []= $date . 'UTC';
}
for($start_z = microtime(true), $i = 0; $i < $counter; $i++) $tmp = strtotime($times_z[$i]);
$dur_z = microtime(true) - $start_z;
for($start_u = microtime(true), $i = 0; $i < $counter; $i++) $tmp = strtotime($times_utc[$i]);
$dur_u = microtime(true) - $start_u;
for($start_u2 = microtime(true), $i = 0; $i < $counter; $i++) $tmp =
strtotime(str_replace('Z', 'UTC', $times_utc[$i]));
$dur_u2 = microtime(true) - $start_u2;
echo 'Z took ' . number_format($dur_z, 4) . 's, UTC took ' .
number_format($dur_u, 4) . 's, Z with str_replace to UTC took ' . number_format($dur_u2,
4) . 's' . $br;
if ($dur_z <= $dur_u) echo 'UTC format was ' . (number_format($dur_u / $dur_z, 2)) .
' times slower than Z' . $br;
else echo 'Z format was ' . (number_format($dur_z / $dur_u, 2)) . ' times slower than
UTC' . $br;
Expected result:
----------------
I would expect to see UTC and Z versions having similar parsing times.
Actual result:
--------------
On windows with PHP 5.4.11, Z format parsing is 7 times slower than UTC version,
using str_replace for all dates (Z => UTC) is 1.1 times slower than UTC version.
On windows with PHP 5.3.21, Z format parsing is 6.1 times slower than UTC version,
using str_replace for all dates (Z => UTC) is 1.1 times slower than UTC version.
On Linux server with PHP 5.3.20 + APC, Z format parsing is 5 times slower than UTC
version, using str_replace for all dates (Z => UTC) is 1.15 times slower than UTC
version.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=64188&edit=1