32 votes

Pourquoi date() travaille deux fois plus vite si nous définir le fuseau horaire à partir du code?

Avez-vous remarqué qu' date() fonction 2x plus rapide que d'habitude si vous définissez réelle fuseau horaire à l'intérieur de votre script avant tout date() appel? Je suis très curieux à ce sujet.

Regardez ce simple morceau de code:

<?php

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

?>

Il appelle juste date() fonction à l'aide d' for boucle de 100 000 fois. Le résultat que j'ai obtenu est toujours autour de 1,6 secondes (Windows, PHP 5.3.5) mais...

Si j'ai mis en même temps la zone de nouveau en ajoutant une absurde ligne avant de commencer:

date_default_timezone_set(date_default_timezone_get());

Je reçois une fois en dessous de 800ms; ~2x plus rapide (le même serveur).

Je regardais autour de moi pour trouver une quelconque explication raisonnable à ce problème, mais n'a pas de succès. De mon point de vue, cette ligne supplémentaire est inutile, mais PHP n'est pas d'accord avec moi.

J'ai essayé ce test sur les deux serveurs linux (versions différentes de PHP) et a obtenu différentes résultant fois, mais en proportion ~6:1.

Remarque: la date.le fuseau horaire de la propriété en php.ini a été correctement définie (Europe/Paris).

J'étais à la recherche pour les questions ici et de ne pas trouver quelque chose de similaire. J'ai également vérifié manuel pour date_default_time_zone() la fonction @ php.net et vu que je suis pas le seul qui a remarqué ça, mais ne peut toujours pas comprendre pourquoi ça arrive?

N'importe qui?


MERCI LES GARS, J'AI VRAIMENT APPRÉCIER TOUTES VOS RÉPONSES ET COMMENTAIRES.

41voto

Jon Points 194296

Mise à jour de PHP 5.4:

Comme indiqué dans la description de l' date_default_timezone_get, à partir de PHP 5.4.0 l'algorithme de deviner le fuseau horaire du système d'information a été retirée du code (qui contraste avec le PHP 5.3 source), donc ce problème n'existe plus.

L'exécution de la synchronisation test sur mon serveur de dev de le voir en action, je me suis fait:

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

Réponse originale à cette question:

J'ai juste regardé dans les sources de PHP. Précisément, tout le code est en /ext/date/php_date.c.

J'ai commencé avec l'hypothèse que, si vous ne fournissez pas un fuseau horaire pour date, date_default_timezone_get est appelé à en obtenir un. Voici la fonction:

PHP_FUNCTION(date_default_timezone_get)
{
    timelib_tzinfo *default_tz;

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

OK, alors qu'est - get_timezone_info ressemble? Ce:

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'en guess_timezone? Ici, il 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, alors comment ne qui interagissent avec date_default_timezone_set? Regardons cette fonction:

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

Longue histoire courte: si vous appelez date_default_timezone_set une fois, alors guess_timezone prend la voie rapide de la lecture de l' timezone variable (la première condition est satisfaite, et il revient tout de suite). Sinon, il faut un certain temps à travailler sur le fuseau horaire par défaut, ce qui n'est pas mis en cache (je suppose que pour des raisons de simplicité), et si vous le faites dans une boucle, le délai commence à montrer.

2voto

GordonM Points 14008

J'imagine qu'il doit déterminer le fuseau horaire pour elle-même chaque fois qu'il est appelé, sauf si expressément spécifié, ce qui ajoute à la fonction d'exécution.

Mais vraiment, est-il question? Combien de scripts êtes-vous susceptible de faire cet appel date() de 100 000 fois par course?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X