Wh1*_*Ck5 32 php timezone datetime micro-optimization
您是否注意到如果您在任何调用之前在脚本中设置实际时区,那么该date()函数的工作速度比平时快2倍date()?我对此非常好奇.
看看这段简单的代码:
<?php
$start = microtime(true);
for ($i = 0; $i < 100000; $i++) date('Y-m-d H:i:s');
echo (microtime(true) - $start);
?>
Run Code Online (Sandbox Code Playgroud)
它只date()使用for循环100,000次调用函数.我得到的结果总是大约1.6秒(Windows,PHP 5.3.5),但......
如果我在开始之前再次设置相同的时区添加一条荒谬的行:
date_default_timezone_set(date_default_timezone_get());
Run Code Online (Sandbox Code Playgroud)
我得到的时间低于800毫秒 ; 快2倍(同一台服务器).
我正四处寻找这种行为的任何合理解释,但没有任何成功.从我的角度来看,这个额外的行没用,但PHP不同意我的看法.
我已经在两个Linux服务器(不同的PHP版本)上尝试了这个测试,并且得到了不同的结果时间,但比例为6:1.
注意:php.ini中的date.timezone属性已正确设置(欧洲/巴黎).
我在这里搜索相关问题并没有找到类似的东西.我还检查了date_default_time_zone()函数@php.net的手册,发现我不仅是一个注意到这一点的人,但仍然无法理解为什么会发生这种情况?
任何人?
Jon*_*Jon 41
正如在描述中所述date_default_timezone_get,从PHP 5.4.0开始,从代码中删除了从系统信息中猜测时区的算法(与PHP 5.3源代码对比),因此这种行为不再存在.
在我的开发服务器上运行定时测试以查看它的运行情况,我得到了:
我刚刚研究了PHP源代码.具体来说,所有相关代码都在/ext/date/php_date.c.
我开始假设如果你没有提供时区date,date_default_timezone_get就会调用它来获得一个.这是功能:
PHP_FUNCTION(date_default_timezone_get)
{
timelib_tzinfo *default_tz;
default_tz = get_timezone_info(TSRMLS_C);
RETVAL_STRING(default_tz->name, 1);
}
Run Code Online (Sandbox Code Playgroud)
好的,那get_timezone_info看起来像什么?这个:
PHPAPI timelib_tzinfo *get_timezone_info(TSRMLS_D)
{
char *tz;
timelib_tzinfo *tzi;
tz = guess_timezone(DATE_TIMEZONEDB TSRMLS_CC);
tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC);
if (! tzi) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Timezone database is corrupt - this should *never* happen!");
}
return tzi;
}
Run Code Online (Sandbox Code Playgroud)
怎么样guess_timezone?这是:
static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC)
{
char *env;
/* Checking configure timezone */
if (DATEG(timezone) && (strlen(DATEG(timezone)) > 0)) {
return DATEG(timezone);
}
/* Check environment variable */
env = getenv("TZ");
if (env && *env && timelib_timezone_id_is_valid(env, tzdb)) {
return env;
}
/* Check config setting for default timezone */
/* ..... code omitted ....... */
#if HAVE_TM_ZONE
/* Try to guess timezone from system information */
/* ..... code omitted ....... */
#endif
#ifdef PHP_WIN32
/* ..... code omitted ....... */
#elif defined(NETWARE)
/* ..... code omitted ....... */
#endif
/* Fallback to UTC */
php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We had to select 'UTC' because your platform doesn't provide functionality for the guessing algorithm");
return "UTC";
}
Run Code Online (Sandbox Code Playgroud)
好的,那么它如何与之互动date_default_timezone_set呢?我们来看看这个功能:
PHP_FUNCTION(date_default_timezone_set)
{
char *zone;
int zone_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &zone, &zone_len) == FAILURE) {
RETURN_FALSE;
}
if (!timelib_timezone_id_is_valid(zone, DATE_TIMEZONEDB)) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Timezone ID '%s' is invalid", zone);
RETURN_FALSE;
}
if (DATEG(timezone)) {
efree(DATEG(timezone));
DATEG(timezone) = NULL;
}
DATEG(timezone) = estrndup(zone, zone_len);
RETURN_TRUE;
}
Run Code Online (Sandbox Code Playgroud)
长话短说:如果你调用date_default_timezone_set一次,那么guess_timezone从timezone变量中读取快速读取路径(第一个条件满足,并立即返回).否则需要一些时间来计算默认时区,这个时区没有缓存(我想简单来说),如果你在循环中这样做,延迟开始显示.
| 归档时间: |
|
| 查看次数: |
2037 次 |
| 最近记录: |