La mémoire fuit Symfony2 Docsortingne2 / dépasse la limite de mémoire

En fait, j’ai beaucoup de problèmes avec la combinaison de symfony2 et de docsortingne2. Je dois gérer des ensembles de données énormes (environ 2 à 3 millions d’écrits et de lectures) et faire beaucoup d’efforts pour éviter de manquer de mémoire.

J’ai figuré 2 points principaux, qui “fuient” la mémoire (ils ne fuient pas vraiment, mais en atsortingbuant beaucoup)

  1. Le stockage d’entité Entitymanager (je ne connais pas le vrai nom de celui-ci) il semble qu’il garde toutes les entités traitées et vous devez effacer ce stockage régulièrement avec

      $ entityManager-> clear () 
  2. The Docsortingne QueryCache – il met en cache toutes les requêtes utilisées et la seule configuration que j’ai trouvée était que vous pouviez décider quel type de cache vous souhaitez utiliser. Je n’ai pas trouvé de désactivation globale ni un indicateur utile pour chaque requête pour le désactiver. Donc, généralement, le désactiver pour chaque object de requête avec la fonction

     $ qb = $ repository-> createQueryBuilder ($ a);
     $ query = $ qb-> getQuery ();
     $ query-> useQueryCache (false);
     $ query-> execute ();
    

donc … c’est tout ce que j’ai compris en ce moment .. mes questions sont:

Existe-t-il un moyen facile de refuser certains objects à Entitymanagerstorage? Existe-t-il un moyen de définir l’utilisation de querycache dans le paramètre entitymanager? Puis-je configurer ces comportements de mise en cache dans la configuration de la docsortingne Symonfony?

Serait très cool si quelqu’un a de bons conseils pour moi … sinon cela pourrait aider certaines recrues ..

cya

    Un peu tard, mais je pense que je viens de trouver un fil sur Google Groups de Benjamin Eberlei qui répond à votre question: comme indiqué par le Docsortingne Configuration Reference par défaut, la connexion SQL est définie sur la valeur de kernel.debug , donc Si vous avez instancié AppKernel avec debug défini sur true, les commandes SQL sont stockées en mémoire pour chaque itération.

    Vous devez soit instancier AppKernel sur false , définir la journalisation sur false dans votre configuration YML, soit définir manuellement SQLLogger sur null avant d’utiliser EntityManager.

    $em->getConnection()->getConfiguration()->setSQLLogger(null); 

    Essayez d’exécuter votre commande avec –no-debug . En mode de débogage, le profileur conserve des informations sur chaque requête en mémoire.

    1. Désactivez la journalisation et le profilage dans app/config/config.yml

     docsortingne: dbal: driver: ... ... logging: false profiling: false 

    ou en code

     $this->em->getConnection()->getConfiguration()->setSQLLogger(null); 

    2. Forcer le ramasse-miettes . Si vous utilisez activement CPU, le ramasse-miettes attend et vous pouvez vous retrouver rapidement sans mémoire.

    Tout d’abord, activez la gestion manuelle de la récupération de place. Exécutez gc_enable() n’importe où dans le code. Ensuite, lancez gc_collect_cycles() pour forcer le garbage collector.

    Exemple

     public function execute(InputInterface $input, OutputInterface $output) { gc_enable(); // I'm initing $this->em in __construct using DependencyInjection $customers = $this->em->getRepository('AppBundle:Customer')->findAll(); $counter = 0; foreach ($customers as $customer) { // process customer - some logic here, $this->em->persist and so on if (++$counter % 100 == 0) { $this->em->flush(); // save unsaved changes $this->em->clear(); // clear docsortingne managed entities gc_collect_cycles(); // PHP garbage collect // Note that $this->em->clear() detaches all managed entities, // may be you need some; reinit them here } } // don't forget to flush in the end $this->em->flush(); $this->em->clear(); gc_collect_cycles(); } 

    Si votre table est très grande, n’utilisez pas findAll . Utiliser un iterator – http://docsortingne-orm.readthedocs.org/projects/docsortingne-orm/en/latest/reference/batch-processing.html#iterating-results

    1. Définir le journal SQL sur null

    $em->getConnection()->getConfiguration()->setSQLLogger(null);

    1. Appelez manuellement la fonction gc_collect_cycles() après $em->clear()

    $em->clear(); gc_collect_cycles();

    N’oubliez pas de définir zend.enable_gc sur 1 ou d’appeler manuellement gc_enable () avant d’utiliser gc_collect_cycles ()

    1. Ajoutez l’option --no-debug si vous exécutez la commande depuis la console.

    a obtenu des nouvelles “drôles” des développeurs de docsortingne eux-mêmes sur le live de symfony à Berlin – ils disent que sur les gros lots, nous ne devrions pas utiliser un orm .. ce n’est pas efficace pour construire des choses comme ça dans oop

    .. ouais .. peut-être qu’ils ont raison xD

    Conformément à la documentation standard de Docsortingne2, vous devez effacer ou détacher manuellement les entités.

    En plus de cela, lorsque le profilage est activé (comme dans l’environnement de développement par défaut). DocsortingneBundle dans Symfony2 configure plusieurs enregistreurs qui utilisent beaucoup de mémoire. Vous pouvez désactiver la journalisation complètement, mais ce n’est pas obligatoire.

    Un effet secondaire intéressant est que les enregistreurs affectent à la fois Docsortingne ORM et DBAL. L’un des enregistreurs entraînera une utilisation supplémentaire de la mémoire pour tout service utilisant le service de journalisation par défaut. Désactiver tous ces éléments serait idéal dans les commandes, car le profileur n’y est pas encore utilisé.

    Voici ce que vous pouvez faire pour désactiver les enregistreurs intenses en mémoire tout en conservant la fonction de profilage activée dans d’autres parties de Symfony2:

     $c = $this->getContainer(); /* * The default dbalLogger is configured to keep "stopwatch" events for every query executed * the only way to disable this, as of Symfony 2.3, Docsortingne Bundle 1.2, is to reinistiate the class */ $dbalLoggerClass = $c->getParameter('docsortingne.dbal.logger.class'); $dbalLogger = new $dbalLoggerClass($c->get('logger')); $c->set('docsortingne.dbal.logger', $dbalLogger); // sometimes you need to configure docsortingne to use the newly logger manually, like this $docsortingneConfiguration = $c->get('docsortingne')->getManager()->getConnection()->getConfiguration(); $docsortingneConfiguration->setSQLLogger($dbalLogger); /* * If profiling is enabled, this service will store every query in an array * fortunately, this is configurable with a property "enabled" */ if($c->has('docsortingne.dbal.logger.profiling.default')) { $c->get('docsortingne.dbal.logger.profiling.default')->enabled = false; } /* * When profiling is enabled, the Monolog bundle configures a DebugHandler that * will store every log messgae in memory. * * As of Monolog 1.6, to remove/disable this logger: we have to pop all the handlers * and then push them back on (in the correct order) */ $handlers = array(); try { while($handler = $logger->popHandler()) { if($handler instanceOf \Symfony\Bridge\Monolog\Handler\DebugHandler) { continue; } array_unshift($handlers, $handler); } } catch(\LogicException $e) { /* * As of Monolog 1.6, there is no way to know if there's a handler * available to pop off except for the \LogicException that's thrown. */ if($e->getMessage() != 'You sortinged to pop from an empty handler stack.') { /* * this probably doesn't matter, and will probably break in the future * this is here for the sake of people not knowing what they're doing * so than an unknown exception is not silently discarded. */ // remove at your own risk throw $e; } } // push the handlers back on foreach($handlers as $handler) { $logger->pushHandler($handler); } 

    Essayez de désactiver les caches Docsortingne existants. (Si vous n’utilisez pas APC / autre comme cache, la mémoire est utilisée).

    Supprimer le cache de requêtes

     $qb = $repository->createQueryBuilder($a); $query = $qb->getQuery(); $query->useQueryCache(false); $query->useResultCache(false); $query->execute(); 

    Il n’y a aucun moyen de le désactiver globalement

    C’est aussi une alternative à effacer qui pourrait aider (à partir d’ ici )

     $connection = $em->getCurrentConnection(); $tables = $connection->getTables(); foreach ( $tables as $table ) { $table->clear(); } 

    Je viens de poster un tas de conseils pour utiliser les commandes de la console Symfony avec Docsortingne pour le traitement par lots ici .