php - zona - ¿Por qué date() funciona el doble de rápido si configuramos el huso horario del código?
zona horaria (2)
Actualización para PHP 5.4:
Como se documenta en la descripción de date_default_timezone_get
, a partir de PHP 5.4.0, el algoritmo para adivinar la zona horaria a partir de la información del sistema se ha eliminado del código (contraste con la fuente PHP 5.3) por lo que este comportamiento ya no existe.
Ejecutando la prueba de tiempo en mi servidor de desarrollo para verlo en acción, obtuve:
- PHP 5.3.11: ~ 720 ms
- PHP 5.4.3: ~ 470ms
Respuesta original:
Acabo de examinar la fuente PHP. Específicamente, todo el código relevante está en /ext/date/php_date.c
.
Empecé con la suposición de que si no proporciona una zona horaria para la date
, se llama a date_default_timezone_get
para obtener una. Aquí está esa función :
PHP_FUNCTION(date_default_timezone_get)
{
timelib_tzinfo *default_tz;
default_tz = get_timezone_info(TSRMLS_C);
RETVAL_STRING(default_tz->name, 1);
}
OK, ¿ get_timezone_info
ve get_timezone_info
? 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;
}
¿Qué hay de guess_timezone
? Here está:
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, entonces, ¿cómo interactúa eso con date_default_timezone_set
? Veamos esa función :
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;
}
Para date_default_timezone_set
, si llama a date_default_timezone_set
una vez, entonces guess_timezone
toma la ruta rápida de lectura de la variable de la timezone
(se cumple el primer condicional y vuelve inmediatamente). De lo contrario, lleva un tiempo calcular la zona horaria predeterminada, que no está en la memoria caché (supongo que por simplicidad), y si lo hace en un bucle, la demora comienza a mostrarse.
¿Ha notado que la función de date()
funciona 2 veces más rápido de lo normal si establece la zona horaria actual dentro de su secuencia de comandos antes de cualquier llamada a la date()
? Tengo mucha curiosidad sobre esto.
Mire esta simple pieza de código:
<?php
$start = microtime(true);
for ($i = 0; $i < 100000; $i++) date(''Y-m-d H:i:s'');
echo (microtime(true) - $start);
?>
Simplemente llama a la función date()
usando for
loop 100,000 veces. El resultado que obtengo es siempre de alrededor de 1,6 segundos (Windows, PHP 5.3.5) pero ...
Si configuro el mismo huso horario agregando una línea absurda antes de comenzar:
date_default_timezone_set(date_default_timezone_get());
Tengo un tiempo inferior a 800 ms ; ~ 2 veces más rápido (el mismo servidor).
Estaba buscando una explicación razonable para este comportamiento pero no tuve éxito. Desde mi punto de vista, esta línea adicional es inútil, pero PHP no está de acuerdo conmigo.
He probado esta prueba en dos servidores de Linux (diferentes versiones de PHP) y obtuve diferentes tiempos resultantes, pero en proporción ~ 6: 1 .
Nota: la propiedad date.timezone en php.ini se ha establecido correctamente (Europa / París).
Estaba buscando preguntas relacionadas aquí y no encontré nada similar. También revisé el manual de date_default_time_zone () function @ php.net y descubrí que no solo soy alguien que notó esto, ¿pero todavía no puedo entender por qué sucede eso?
¿Nadie?
Me imagino que tiene que determinar la zona horaria por sí misma cada vez que se invoca a menos que se especifique explícitamente, lo que se agrega al tiempo de ejecución de la función.
Pero realmente, ¿Importa? ¿Cuántas secuencias de comandos es probable que realice esa llamada a la fecha () 100.000 veces por ejecución?