Follow-up to #2421451: Drupal needs comments in opcache
Problem/Motivation
SimpleAnnotationReader
loads classes while parsing them. This puts more things in the opcache than we would like.
Doctrine has essentially "won't fixed" this bug, since they're planning to deprecate SimpleAnnotationReader
.
References:
https://github.com/doctrine/common/issues/607
https://github.com/doctrine/annotations/issues/87
https://github.com/doctrine/annotations/pull/199
AnnotationReader
itself both loads classes and uses reflection, this is much too memory heavy for Drupal given the number of plugins in core, and is the reason we contributed to SimpleAnnotationReader
in the first place.
At this point, we are only using SimpleAnnotationReader
so that it can parse the docblock, which we then pass on to other code which does not use reflection.
Doctrine's support cycle is out of sync with ours, since they already require PHP 5.6.
Proposed resolution
We need our own annotation parser, as a component, which uses the PHP tokenizer rather than reflection and doesn't load any classes as PHP.
The drupal/core-annotation subtree split will allow other projects to use that if they wish.
Some Analysis
Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery:: getDefinitions()
uses a Doctrine\Common\Annotations\SimpleAnnotationReader
to get the annotation from the class declaration: http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Component/Annotat...
SimpleAnnotationReader::getClassAnnotation()
requires a ReflectionClass
which causes the class to be loaded. That's the problem we're trying to solve.
Then the reflection object is used to get the docblock, because it's super convenient. :-) It also eats up memory and op cache.
So basically our replacement should not require a ReflectionClass
for SimpleAnnotationReader::getClassAnnotation()
. We already have the path, so instead of generating a ReflectionClass
(with MockFileFinder
and StaticReflectionParser
), we should pass in the path. It then does token parsing to find the class declaration and the docblock immediately before it.