From 754d3a7568b1df9aa8871eddc065cc1dcc025a56 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 10 Jul 2017 10:56:59 +0200 Subject: [PATCH] [HttpKernel][VarDumper] Truncate profiler data & optim perf --- .../DataCollector/FormDataCollector.php | 87 ++++++------------- src/Symfony/Component/Form/composer.json | 6 +- .../DataCollector/DataCollector.php | 43 +++++++-- .../Component/VarDumper/Caster/Caster.php | 13 ++- .../VarDumper/Caster/ExceptionCaster.php | 4 +- .../VarDumper/Cloner/AbstractCloner.php | 16 ++-- 6 files changed, 84 insertions(+), 85 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index b088abc7962f6..7540449b96ec5 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -20,11 +20,7 @@ use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ClassStub; -use Symfony\Component\VarDumper\Caster\CutStub; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\Stub; -use Symfony\Component\VarDumper\Cloner\VarCloner; /** * Data collector for {@link FormInterface} instances. @@ -77,11 +73,6 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf */ private $valueExporter; - /** - * @var ClonerInterface - */ - private $cloner; - private $hasVarDumper; public function __construct(FormDataExtractorInterface $dataExtractor) @@ -255,61 +246,33 @@ public function serialize() /** * {@inheritdoc} */ - protected function cloneVar($var, $isClass = false) + protected function getCasters() { - if ($var instanceof Data) { - return $var; - } - if (null === $this->cloner) { - if ($this->hasVarDumper) { - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(-1); - $this->cloner->addCasters(array( - '*' => function ($v, array $a, Stub $s, $isNested) { - foreach ($a as &$v) { - if (is_object($v) && !$v instanceof \DateTimeInterface) { - $v = new CutStub($v); - } - } - - return $a; - }, - \Exception::class => function (\Exception $e, array $a, Stub $s) { - if (isset($a[$k = "\0Exception\0previous"])) { - unset($a[$k]); - ++$s->cut; - } - - return $a; - }, - FormInterface::class => function (FormInterface $f, array $a) { - return array( - Caster::PREFIX_VIRTUAL.'name' => $f->getName(), - Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), - ); - }, - ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) { - return array( - Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(), - Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(), - Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(), - ); - }, - )); - } else { - @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED); - $this->cloner = false; - } - } - if (false !== $this->cloner) { - return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE); - } - - if (null === $this->valueExporter) { - $this->valueExporter = new ValueExporter(); - } + return parent::getCasters() + array( + \Exception::class => function (\Exception $e, array $a, Stub $s) { + foreach (array("\0Exception\0previous", "\0Exception\0trace") as $k) { + if (isset($a[$k])) { + unset($a[$k]); + ++$s->cut; + } + } - return $this->valueExporter->exportValue($var); + return $a; + }, + FormInterface::class => function (FormInterface $f, array $a) { + return array( + Caster::PREFIX_VIRTUAL.'name' => $f->getName(), + Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), + ); + }, + ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) { + return array( + Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(), + Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(), + Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(), + ); + }, + ); } private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash) diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 5a1d6ef9cba51..85250b87f357b 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -29,7 +29,7 @@ "symfony/dependency-injection": "~3.3", "symfony/config": "~2.7|~3.0", "symfony/http-foundation": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0", + "symfony/http-kernel": "^3.3.5", "symfony/security-csrf": "~2.8|~3.0", "symfony/translation": "~2.8|~3.0", "symfony/var-dumper": "~3.3" @@ -39,8 +39,8 @@ "symfony/dependency-injection": "<3.3", "symfony/doctrine-bridge": "<2.7", "symfony/framework-bundle": "<2.7", - "symfony/twig-bridge": "<2.7", - "symfony/var-dumper": "<3.3" + "symfony/http-kernel": "<3.3.5", + "symfony/twig-bridge": "<2.7" }, "suggest": { "symfony/validator": "For form validation.", diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php index 0d574eae3b3af..770c985637da6 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php @@ -12,9 +12,10 @@ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; -use Symfony\Component\VarDumper\Caster\ClassStub; +use Symfony\Component\VarDumper\Caster\CutStub; use Symfony\Component\VarDumper\Cloner\ClonerInterface; use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\Stub; use Symfony\Component\VarDumper\Cloner\VarCloner; /** @@ -37,7 +38,7 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable /** * @var ClonerInterface */ - private static $cloner; + private $cloner; public function serialize() { @@ -61,16 +62,20 @@ public function unserialize($data) */ protected function cloneVar($var) { - if (null === self::$cloner) { - if (class_exists(ClassStub::class)) { - self::$cloner = new VarCloner(); - self::$cloner->setMaxItems(-1); + if ($var instanceof Data) { + return $var; + } + if (null === $this->cloner) { + if (class_exists(CutStub::class)) { + $this->cloner = new VarCloner(); + $this->cloner->setMaxItems(-1); + $this->cloner->addCasters(self::getCasters()); } else { @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED); - self::$cloner = false; + $this->cloner = false; } } - if (false === self::$cloner) { + if (false === $this->cloner) { if (null === $this->valueExporter) { $this->valueExporter = new ValueExporter(); } @@ -78,7 +83,7 @@ protected function cloneVar($var) return $this->valueExporter->exportValue($var); } - return self::$cloner->cloneVar($var); + return $this->cloner->cloneVar($var); } /** @@ -100,4 +105,24 @@ protected function varToString($var) return $this->valueExporter->exportValue($var); } + + /** + * @return callable[] The casters to add to the cloner + */ + protected function getCasters() + { + return array( + '*' => function ($v, array $a, Stub $s, $isNested) { + if (!$v instanceof Stub) { + foreach ($a as $k => $v) { + if (is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) { + $a[$k] = new CutStub($v); + } + } + } + + return $a; + }, + ); + } } diff --git a/src/Symfony/Component/VarDumper/Caster/Caster.php b/src/Symfony/Component/VarDumper/Caster/Caster.php index a0efa651b9258..b1e67cb30a035 100644 --- a/src/Symfony/Component/VarDumper/Caster/Caster.php +++ b/src/Symfony/Component/VarDumper/Caster/Caster.php @@ -65,11 +65,20 @@ public static function castObject($obj, $class, $hasDebugInfo = false) } if ($a) { + static $publicProperties = array(); + $i = 0; $prefixedKeys = array(); foreach ($a as $k => $v) { - if (isset($k[0]) && "\0" !== $k[0] && !property_exists($class, $k)) { - $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; + if (isset($k[0]) && "\0" !== $k[0]) { + if (!isset($publicProperties[$class])) { + foreach (get_class_vars($class) as $prop => $v) { + $publicProperties[$class][$prop] = true; + } + } + if (!isset($publicProperties[$class][$k])) { + $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; + } } elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { $prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0"); } diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index f1f58c0a87263..6786cf6a11803 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -102,7 +102,7 @@ public static function castSilencedErrorContext(SilencedErrorContext $e, array $ } unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); - $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace); + $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); return $a; } @@ -256,7 +256,7 @@ private static function filterExceptionArray($xClass, array $a, $xPrefix, $filte $trace = array(); } - if (!($filter & Caster::EXCLUDE_VERBOSE)) { + if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) { if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); } diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index c07ae491c5dc0..45e0b6ad771b1 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -209,15 +209,17 @@ public function cloneVar($var, $filter = 0) }); $this->filter = $filter; + if ($gc = gc_enabled()) { + gc_disable(); + } try { $data = $this->doClone($var); - } catch (\Exception $e) { - } - restore_error_handler(); - $this->prevErrorHandler = null; - - if (isset($e)) { - throw $e; + } finally { + if ($gc) { + gc_enable(); + } + restore_error_handler(); + $this->prevErrorHandler = null; } return new Data($data);