le début de la session() prend beaucoup de temps

le site Mys fonctionne très lentement (et je ne savais pas pourquoi). Il est basé sur L'Application Zend, j'avais l'habitude de faire des dizaines de tels sites, donc je suis sûr que mon code est OK.

j'ai installé xdebugger sur le serveur, essayé de le profiler et devinez quoi? php::session_start() a pris 48.675 secondes. Quarante Huit Secondes et Demi! C'est incroyable! Quelle pourrait être la raison de cela? C'est une opération courante, pourquoi pourrait-elle être exécutée si longtemps? Comment corriger un tel comportement, qui configure modifier? Cherché sur Google, mais n'a trouvé aucune bonne réponse (presque partout Il ya une question, mais pas de réponse). Merci en avant!

xdebugger profiling results

21
demandé sur ABTOMAT 2012-12-08 02:32:16

8 réponses

session_start (avec des sessions stockées dans des fichiers) bloque en PHP, donc ce problème apparaîtra si vous essayez de lancer plusieurs sessions de serveur pour la même session de navigateur (AJAX ou plusieurs onglets de navigateur/windows). session_start attendra que les autres sessions soient closes.

http://konrness.com/php5/how-to-prevent-blocking-php-requests/

essayez de passer des fichiers au stockage de base de données des sessions.

18
répondu Christian Davén 2013-03-07 07:47:18

a mon avis, il s'agit de la routine de collecte des ordures, qui est exécutée à l'intérieur de l'indigène session_start() fonction. Peut-être avez-vous fait quelque chose qui garde beaucoup de vieux dossiers de session autour, comme changé le temps de vie max? Ou peut-être avez-vous décidé que ce serait une bonne idée de les stocker dans une base de données, mais avez-vous oublié de créer un index approprié? Le stat () natif de routine GC est un fichier de chaque session pour vérifier l'expiration. Cela prend du temps s'il y a beaucoup de fichiers construits jusqu'.

modifier: afin de vous aider pour le débogage seulement, désactiver la collecte des ordures en installant Temporairement session.gc-probabilité:

session.gc-probability = 0

assurez-vous que les paramètres tiennent, Je ne sais pas ce que le cadre zend pourrait faire ici.

18
répondu goat 2014-10-15 12:07:20

j'ai eu ce problème et je suis surpris que personne n'a posté cette réponse spécifique. Ce n'est peut-être pas le cas, mais cela vaut la peine d'être vérifié.

PHP verrouille le fichier de SESSION pendant qu'une page est en cours de traitement, de sorte que cette page puisse y avoir un accès exclusif. Pensez-y, le fichier sess_184c9aciqoc n'est pas une base de données, donc deux appels dans la même session ne peuvent pas y accéder simultanément. Donc, si vous avez beaucoup d'appels ajax, vous pouvez obtenir un "embouteillage". Une fois que vous commencez à faire des scripts avancés est une chasse aux sorcières à l'attention de. par ailleurs, voici une fonction pour stocker un tableau de l'horodatage. J'ai utilisé pour comprendre démarrage de la session était le coupable:

//time function for benchmarking
if( function_exists('gmicrotime')){
    function gmicrotime($n=''){
        #version 1.1, 2007-05-09
        //store array of all calls
        global $mT;
        list($usec, $sec) = explode(' ',microtime());
        if(!isset($mT['_base_']))$mT['_base_']=$sec;
    $t=round((float)$usec + (float)(substr($sec,-4)),6);
    $mT['all'][]=$t;
    if($n){
        if(isset($mT['indexed'][$n])){
            //store repeated calls with same index.  If in a loop, add a $i if needed
            if(is_array($mT['indexed'][$n])){
                $mT['indexed'][$n][]=$t;
            }else{
                $mT['indexed'][$n]=array($mT['indexed'][$n],$t);
            }
        }else $mT['indexed'][$n]=$t;    
    }
    //return elapsed since last call (in the local array)
    $u=$mT['all'];
    if(count($u)>1){
        $mT['_total_']=$u[count($u)-1] - $u[0];
        return round(1000*($u[count($u)-1]-$u[count($u)-2]),6);
    }
}
gmicrotime('pageStart');
}

puis-je appeler comme suit:

gmicrotime('beforeSessionStart');
session_start();
gmicrotime('afterSessionStart');

do_something_slow();
gmicrotime('afterSlowProcess');
//etc..
echo '<pre>';
print_r($mT);  

J'espère que c'est utile!

5
répondu Samuel Fullman 2014-08-31 03:27:19

une Autre approche pourrait être que vous avez créé un grand memory_limit en PHP.ini.

j'ai fait cela pour télécharger des dumps mysql énormes dans PHPMyAdmin et charger le temps enrichi, peut-être (comme dit ci-dessus) beaucoup de fichiers de session empilés maintenant que PHP avait de la place pour économiser. La valeur par défaut est 128M, je pense. J'avais quadruplé.

1
répondu PeerBr 2014-04-09 19:22:03

une façon d'éviter ce problème est de demander à PHP de stocker les sessions dans une table de base de données au lieu de fichiers.

tout d'abord, je vais vous donner quelques liens comme de vrais crédits pour ceci solution:

http://www.tonymarston.net/php-mysql/session-handler.html

http://shiflett.org/articles/storing-sessions-in-a-database

http://culttt.com/2013/02/04/how-to-save-php-sessions-to-a-database/

Puis une mise en œuvre du code j'ai tiré de ces lectures:

<?php

class TLB_Sessions_in_Database
{
    private $debug;
    private $dbc;

    function __construct()
    {
        $this->debug = false;

        session_set_save_handler(
            array($this, '_open'),
            array($this, '_close'),
            array($this, '_read'),
            array($this, '_write'),
            array($this, '_destroy'),
            array($this, '_clean')
        );
    }

    function _open()
    {
        if( $this->debug ) echo '_open:'.PHP_EOL;

        if( ($this->dbc = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD)) !== false )
        {
            $select_db = mysql_select_db(DB_NAME, $this->dbc);
            $set_charset = mysql_set_charset(DB_CHARSET, $this->dbc);

            if( $this->debug ) echo '- return: '.(( $select_db && $set_charset ) ? 'true' : 'false').PHP_EOL;

            return( $select_db && $set_charset );
        }
        else
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( false );
    }

    function _close()
    {
        if( $this->debug ) echo '_close:'.PHP_EOL;

        return( mysql_close($this->dbc) );
    }

    function _read($session_id)
    {
        if( $this->debug ) echo '_read:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);

        $sql = "SELECT `session_data` FROM `".DB_NAME."`.`php_sessions` WHERE `session_id` = '".$session_id."'";

        if( $this->debug ) echo '- query: '.$sql.PHP_EOL;

        if( ($result = mysql_query($sql, $this->dbc)) !== false )
        {
            if( !in_array(mysql_num_rows($result), array(0, false), true) )
            {
                $record = mysql_fetch_assoc($result);

                return( $record['session_data'] );
            }
        }
        else
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( '' );
    }

    function _write($session_id, $session_data)
    {
        if( $this->debug ) echo '_write:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);
        $session_data = mysql_real_escape_string($session_data);

        //$sql = "REPLACE INTO `php_sessions` (`session_id`, `last_updated`, `session_data`) VALUES ('".$session_id."', '".time()."', '".$session_data."')";
        $sql = "INSERT INTO `".DB_NAME."`.`php_sessions` (`session_id`, `date_created`, `session_data`) VALUES ('".$session_id."', NOW(), '".$session_data."') ON DUPLICATE KEY UPDATE `last_updated` = NOW(), `session_data` = '".$session_data."'";

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }

    function _destroy($session_id)
    {
        if( $this->debug ) echo '_destroy:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);

        $sql = "DELETE FROM `".DB_NAME."`.`php_sessions` WHERE `session_id` = '".$session_id."'";

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }

    function _clean($max)
    {
        if( $this->debug ) echo '_clean:'.PHP_EOL;

        $sql = 'DELETE FROM `'.DB_NAME.'`.`php_sessions` WHERE `last_updated` < DATE_SUB(NOW(), INTERVAL '.$max.' SECOND)';

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }
}

new TLB_Sessions_in_Database();

FIN.

0
répondu Tristan CHARBONNIER 2015-05-17 18:31:17

si vous avez plusieurs appels ajax simultanés sur la même page cette situation peut causer votre problème.

0
répondu Nicolas Finelli 2016-04-05 18:39:03

dans mon cas, les paramètres du serveur memcache de /etc/php.d/memcached.ini Ici renseignements sur la memcache propriétés et ici est la façon de configurer le stockage dans memcache.

0
répondu vikramaditya234 2017-06-13 07:34:29

je viens d'avoir ce problème. session_start prenait environ 5sec.

mon problème était que j'avais déclaré quelques variables au-dessus.

j'ai déplacé session_start vers le haut et cela prend maintenant quelques millisecondes.

0
répondu Shane Zammit 2017-12-22 15:41:06