php symfony unit-of-work undefined-index memory-limit

php - Error de índice no definido en $ em-> clear() en Symfony2



unit-of-work undefined-index (2)

He escrito un comando de Symfony para importar algunos datos de una API. Funciona, pero el problema es que mi uso de memoria PHP aumenta cuando inserto un JSON grande en mi base de datos. Y mi unitOfWork aumenta en ''2'' después de cada importación activa.

Ya he desarmado todos mis objetos usados ​​y he leído la documentación de Symfony2 cuando quieres hacer un lote masivo: http://www.doctrine-project.org/blog/doctrine2-batch-processing.html

Pero cuando uso $em->clear() mi administrador de entidades da este error:

Aviso: índice no definido: 000000007b56ea7100000000e366c259 en la línea 2228 de ruta a aplicación / vendedor / doctrina / lib / Doctrina / ORM / UnitOfWork.php

Aquí está mi código completo:

/** * @see Command */ protected function configure() { $this ->setName(''ks:user:runkeepersync'') ->setDescription(''Synchroniser les activités d/'un utilisateur runkeeper'') ->setDefinition(array( new InputArgument(''access_token'', InputArgument::REQUIRED, ''Access token''), )) } /** * @see Command */ protected function execute(InputInterface $input, OutputInterface $output) { $accessToken = $input->getArgument(''access_token''); $em = $this->getContainer()->get(''doctrine'')->getEntityManager(); $UserHasServices = $em->getRepository(''KsUserBundle:UserHasServices'')->findOneByToken($accessToken); if (!is_object($UserHasServices) ) { echo "Impossible de trouver l''utilisateur qui possède le jeton ".$accessToken.""; } $user = $UserHasServices->getUser(); $service = $UserHasServices->getService(); echo "avant de requérir l''api : ".memory_get_usage()."/n"; try { $rkApi = $this->getContainer()->get(''ks_user.runkeeper''); $rkApi->setAccessToken($accessToken); $activities = $rkApi->getFitnessActivities(0,25); $nbParPages = 25; $nomberActivitites = $activities->size; $aActivities = $activities->items; $nbPages = floor ($nomberActivitites/$nbParPages); $aEndurance = array("Running", "Cycling", "Mountain Biking", "Walking", "Hiking", "Downhill Skiing", "Cross-Country Skiing", "Snowboarding", "Skating","Wheelchair", "Rowing", "Elliptical", "Other"); $aEnduranceUnderWater = array("Swimming"); $enduranceOnEarthType = $em->getRepository(''KsActivityBundle:SportType'')->findOneByLabel("endurance"); if (!is_object($enduranceOnEarthType) ) { echo "Impossible de trouver le type de sport d''endurance"; } $enduranceUnderWaterType = $em->getRepository(''KsActivityBundle:SportType'')->findOneByLabel("endurance_under_water"); if (!is_object($enduranceUnderWaterType) ) { echo "Impossible de trouver le type de sport d''endurance sous l''eau "; } echo "Après avoir récupéré 25 activités : ".memory_get_usage()."/n"; $a = 0; for($i=0;$i<=$nbPages;$i++){ if($i!=0){ $activities = $rkApi->getFitnessActivities($i,25); $aActivities = $activities->items; } foreach ($aActivities as $activity) { $a = $a+1; $codeSport = $this->formatNameSport($activity->type); $sport = $em->getRepository(''KsActivityBundle:Sport'')->findOneByCodeSport($codeSport); if (!is_object($sport) ) { $sport = new /Ks/ActivityBundle/Entity/Sport(); $sport->setLabel($codeSport); $sport->setCodeSport($codeSport); $sport->setSportType($enduranceOnEarthType); $em->persist($sport); $em->flush(); } $activityDetail = json_decode($rkApi->requestJSONHealthGraph($activity->uri)); if(in_array($activity->type, $aEndurance)){ $urlActivitieDetail = $activityDetail->activity; $ActivitySessionEnduranceOnEarth = new /Ks/ActivityBundle/Entity/ActivitySessionEnduranceOnEarth($user); isset($activity->total_distance)? $ActivitySessionEnduranceOnEarth->setDistance($activity->total_distance) : ""; isset($activity->duration)? $ActivitySessionEnduranceOnEarth->setDuration($this->secondesToTimeDuration($activity->duration)) : ""; isset($activity->start_time)? $ActivitySessionEnduranceOnEarth->setIssuedAt(new /DateTime($activity->start_time)) : ""; $ActivitySessionEnduranceOnEarth->setModifiedAt(new /DateTime(''Now'')); $ActivitySessionEnduranceOnEarth->setSport($sport); isset($activityDetail->total_calories)? $ActivitySessionEnduranceOnEarth->setCalories($activityDetail->total_calories) : ""; isset($activityDetail->climb)? $ActivitySessionEnduranceOnEarth->setElevationGain($activityDetail->climb) : ""; $maxElevation = 0; $minElevation = 10000; if(isset($activityDetail->path)){ foreach($activityDetail->path as $gpsPoint){ if($gpsPoint->altitude > $maxElevation){ $maxElevation = $gpsPoint->altitude; } if($gpsPoint->altitude < $minElevation){ $minElevation = $gpsPoint->altitude; } } $ActivitySessionEnduranceOnEarth->setElevationMin($minElevation); $ActivitySessionEnduranceOnEarth->setElevationMax($maxElevation); } $em->persist($ActivitySessionEnduranceOnEarth); $em->flush(); //Pour chaque activité on a un identifiant relatif au service qu''on synchronise $ActivityComeFromService = new /Ks/ActivityBundle/Entity/ActivityComeFromService(); $ActivityComeFromService->setActivity($ActivitySessionEnduranceOnEarth); $ActivityComeFromService->setService($service); $ActivityComeFromService->setIdWebsiteActivityService($activity->uri); $ActivityComeFromService->setSourceDetailsActivity($rkApi->requestJSONHealthGraph($activity->uri)); $ActivityComeFromService->setTypeSource("JSON"); $em->persist($ActivityComeFromService); $em->flush(); echo "Import de l''activite num ".$a." type :".$activity->type." effectue avec success /n"; unset($ActivitySessionEnduranceOnEarth); unset($ActivityComeFromService); echo "UnitOFWOrk -> ".$em->getUnitOfWork()->size()."/n"; } if(in_array($activity->type, $aEnduranceUnderWater)){ $ActivitySessionEnduranceUnderWater = new /Ks/ActivityBundle/Entity/ActivitySessionEnduranceUnderWater($user); isset($activity->total_distance)? $ActivitySessionEnduranceUnderWater->setDistance($activity->total_distance) : ""; isset($activity->duration)? $ActivitySessionEnduranceUnderWater->setDuration($this->secondesToTimeDuration($activity->duration)) : ""; isset($activity->start_time) && !empty($activity->start_time)? $ActivitySessionEnduranceUnderWater->setIssuedAt(new /DateTime($activity->start_time)) : ""; $ActivitySessionEnduranceUnderWater->setModifiedAt(new /DateTime(''Now'')); $ActivitySessionEnduranceUnderWater->setSport($sport); isset($activityDetail->total_calories)? $ActivitySessionEnduranceUnderWater->setCalories($activityDetail->total_calories) : ""; isset($activityDetail->notes)? $ActivitySessionEnduranceUnderWater->setDescription($activityDetail->notes) : ""; $em->persist($ActivitySessionEnduranceUnderWater); $em->flush(); $ActivityComeFromService = new /Ks/ActivityBundle/Entity/ActivityComeFromService(); $ActivityComeFromService->setActivity($ActivitySessionEnduranceUnderWater); $ActivityComeFromService->setService($service); $ActivityComeFromService->setIdWebsiteActivityService($activity->uri); $ActivityComeFromService->setSourceDetailsActivity($rkApi->requestJSONHealthGraph($activity->uri)); $ActivityComeFromService->setTypeSource("JSON"); $em->persist($ActivityComeFromService); $em->flush(); echo "Import de l''activité num ".$a." type :".$activity->type." effectué avec succès/n"; unset($ActivitySessionEnduranceUnderWater); unset($ActivityComeFromService); } echo "Après chaque activité : ".memory_get_usage()."/n"; unset($sport); unset($activityDetail); $em->clear(); } } } catch (/Exception $e) { throw $e; } }

Gracias, @AdrienBrault. He probado con --env=prod --no-debug , y es cierto que consume menos memoria, pero la memoria sigue aumentando. ¿Cómo puedo realmente borrar el administrador de la entidad? y estabilizar la memoria?


Intenta reiniciar el administrador de entidades con:

$this->getContainer()->get(''doctrine'')->resetEntityManager();

y entonces:

$em = $this->getContainer()->get(''doctrine'')->getEntityManager();


Symfony registra todas las consultas SQL en el entorno de desarrollo, por lo que primero debes desactivarlo.

// disable logger $em->getConnection()->getConfiguration()->setSQLLogger(null);

Puede utilizar detectores de eventos en entidades, también puede aumentar el uso de memoria. Puedes deshabilitarlos así

// remove all listeners foreach ($em->getEventManager()->getListeners() as $event => $listeners) { foreach ($listeners as $listener) { $em->getEventManager()->removeEventListener($event, $listener); } }

Elimine el unset de su código, no hay necesidad de ellos, ya que borra al administrador de entidades en cada paso de su ciclo.

// save and clear $em->flush(); $em->getUnitOfWork()->clear();

Recuerde que la doctrina puede optimizar sus consultas y mejorar el rendimiento si agrupa las consultas en una sola flush . Por lo tanto, la mejor práctica sería ejecutar el flush una vez sobre algunas partes de sus datos. Por ejemplo:

// collect 100 entities and then save them if (($i % 100) == 0) { $em->flush(); $em->getUnitOfWork()->clear(); }