Why date() works twice as fast if we set time zone from code?

后端 未结 2 1914
深忆病人
深忆病人 2020-12-09 07:47

Have you noticed that date() function works 2x faster than usual if you set actual timezone inside your script before any date() c

相关标签:
2条回答
  • 2020-12-09 08:32

    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.

    0 讨论(0)
  • 2020-12-09 08:42

    I'd imagine it has to determine the timezone for itself each time it's called unless explicitly specified, which adds to the function runtime.

    But really, does it matter? How many scripts are you likely to make that call date() 100,000 times per run?

    0 讨论(0)
提交回复
热议问题