如果我们从代码设置时区,那么为什么date()的运行速度是两倍? [英] Why date() works twice as fast if we set time zone from code?

查看:166
本文介绍了如果我们从代码设置时区,那么为什么date()的运行速度是两倍?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您是否注意到,在任何<$ c $之前,如果您将脚本中的实际时区设置为 date() c> date() call?我很好奇这个。



看看这个简单的代码:

 code><?php 

$ start = microtime(true); ($ i = 0; $ i <100000; $ i ++)日期('Y-m-d H:i:s')

echo(microtime(true) - $ start);

?>

它只是调用 date()函数使用循环100,000次。我得到的结果总是在 1.6秒(Windows,PHP 5.3.5),但...



如果我再次设置相同的时区在开始前添加一条荒谬的行:

  date_default_timezone_set(date_default_timezone_get()); 

我的时间低于 800ms ; 〜2x快(相同的服务器)。



我正在寻找找到合适的解释,但没有任何成功。从我的角度来看,这个额外的行是没用的,但是PHP不同意我的看法。



我已经在两个linux服务器(不同的PHP版本)上尝试过这个测试,



注意: php中的 date.timezone 属性.ini 已经正确设置(欧洲/巴黎)。



我在这里搜索相关问题,没有找到任何类似的东西。我还检查了 date_default_time_zone()函数@ php.net的手册,发现我不仅是一个注意到这一点的人,而且还是不明白为什么会发生这种情况。



任何人?






谢谢你,我真的很感谢你的回答和评论。

解决方案

更新PHP 5.4:



date_default_timezone_get ,从PHP 5.4开始。 0从系统信息中猜测时区的算法已被删除从代码(与PHP 5.3源代码相反),所以这个行为不再存在。



运行ti我的开发服务器上的ming测试看到它在行动,我得到:




  • PHP 5.3.11:〜720ms

  • PHP 5.4.3:〜470ms



原始答案:



我刚刚看了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);
}

确定,那么 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,时区数据库已损坏 - 这应该*永远不会发生!
}
return tzi;
}

guess_timezone 这里是:

  static char * guess_timezone(const timelib_tzdb * tzdb TSRMLS_DC)
{
char * env;

/ *检查配置时区* /
如果(DATEG(时区)&(strlen(DATEG(时区))> 0)){
return DATEG时区);
}
/ *检查环境变量* /
env = getenv(TZ);
if(env&& * env&&timelib_timezone_id_is_valid(env,tzdb)){
return env;
}
/ *检查默认时区的配置设置* /
/ * .....代码省略....... * /
#if HAVE_TM_ZONE
/ *尝试从系统信息中猜出时区* /
/ * .....代码省略....... * /
#endif
#ifdef PHP_WIN32
/ * .....代码省略....... * /
#elif defined(NETWARE)
/ * .....代码省略....... * /
#endif
/ *返回UTC * /
php_error_docref(NULL TSRMLS_CC,E_WARNING,DATE_TZ_ERRMSG我们必须选择UTC,因为您的平台不提供猜测功能算法);
返回UTC;
}

确定,那么如何与 date_default_timezone_set 我们来看看那个功能

  PHP_FUNCTION(date_default_timezone_set)
{
char *区;
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,时区ID%s无效)
RETURN_FALSE;
}
if(DATEG(timezone)){
efree(DATEG(timezone));
DATEG(timezone)= NULL;
}
DATEG(timezone)= estrndup(zone,zone_len);
RETURN_TRUE;
}

长篇小说:如果您调用 date_default_timezone_set 一次,然后 guess_timezone timezone 变量(第一个条件满意,并立即返回)。否则,需要一些时间来制定默认的时区,这不是缓存的(我想是为了简单起见),如果你在循环中这样做,延迟开始显示。


Have you noticed that date() function works 2x faster than usual if you set actual timezone inside your script before any date() call? I'm very curious about this.

Look at this simple piece of code:

<?php

  $start = microtime(true);
  for ($i = 0; $i < 100000; $i++) date('Y-m-d H:i:s');
  echo (microtime(true) - $start);

?>

It just calls date() function using for loop 100,000 times. The result I’ve got is always around 1.6 seconds (Windows, PHP 5.3.5) but…

If I set same time zone again adding one absurd line before start:

date_default_timezone_set(date_default_timezone_get());

I get a time below 800ms; ~2x faster (same server).

I was looking around to find any reasonable explanation for this behavior but did not have any success. From my angle, this additional line is useless but PHP doesn’t agree with me.

I have tried this test on two linux servers (different PHP versions) and got different resulting times but in proportion ~6:1.

Note: date.timezone property in php.ini has been properly set (Europe/Paris).

I was searching for related questions here and did not find anything similar. I've also checked manual for date_default_time_zone() function @ php.net and found that I'm not only one who noticed this, but still can't understand why that happens?

Anyone?


THANK YOU GUYS, I REALLY APPRECIATE ALL YOUR ANSWERS AND COMMENTS.

解决方案

Update for PHP 5.4:

As documented in the description of date_default_timezone_get, starting from PHP 5.4.0 the algorithm to guess the timezone from system information has been removed from the code (contrast with the PHP 5.3 source) so this behavior no longer exists.

Running the timing test on my dev server to see it in action, I got:

  • PHP 5.3.11: ~720ms
  • PHP 5.4.3: ~470ms

Original answer:

I 've just looked into PHP source. Specifically, all relevant code is in /ext/date/php_date.c.

I started with the assumption that if you don't provide a timezone for date, date_default_timezone_get is called to get one. Here's that function:

PHP_FUNCTION(date_default_timezone_get)
{
    timelib_tzinfo *default_tz;

    default_tz = get_timezone_info(TSRMLS_C);
    RETVAL_STRING(default_tz->name, 1);
}

OK, so what does get_timezone_info look like? This:

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;
}

What about guess_timezone? Here it is:

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";
}

OK, so how does that interact with date_default_timezone_set? Let's look at that function:

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;
}

Long story short: if you call date_default_timezone_set once, then guess_timezone takes the fast path of reading from the timezone variable (the very first conditional is satisfied, and it returns immediately). Otherwise it takes some time to work out the default timezone, which is not cached (I guess for simplicity), and if you do that in a loop the delay starts to show.

这篇关于如果我们从代码设置时区,那么为什么date()的运行速度是两倍?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆