rector: Massive slowdown after upgrading to Rector 0.12.22

Bug Report

Subject Details
Rector version 0.12.22

After upgrading to from 0.12.21 to 0.12.22, I experience a massive slowdown. The most extreme slowdown seems to originate from the SymfonyLevelSetList::UP_TO_SYMFONY_60 setlist, but also without that setlist you can see a more than 2 times slowdown on my codebase.

I have run the following command to test (explictly with clear cache every time), limited to a subdirectory to speed up:

time cs_tools/vendor/bin/rector process  --autoload-file=vendor/autoload.php --clear-cache src/Service
Rector version UP_TO_SYMFONY_60 enabled Time Slowdown factor
0.12.21 yes real 1m10.599s / user 1m8.372s / sys 0m1.902s -
0.12.22 yes real 10m2.571s / user 10m0.432s / sys 0m1.907s ~9x
0.12.21 no real 0m28.561s / user 0m26.901s / sys 0m1.571s -
0.12.22 no real 0m57.258s / user 0m55.734s / sys 0m1.484s ~2x

I’m still waiting on the full folder analysis being done in my automated pipeline, which is current already working for 55 minutes while it took about 10 minutes before the upgrade πŸ˜… (I guess it will be killed before it completes - yes, it did indeed)

rector.php
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Doctrine\Set\DoctrineSetList;
use Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector;
use Rector\Php74\Rector\Property\TypedPropertyRector;
use Rector\Php80\Rector\Class_\AnnotationToAttributeRector;
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
use Rector\Php80\ValueObject\AnnotationToAttribute;
use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
use Rector\Symfony\Set\SensiolabsSetList;
use Rector\Symfony\Set\SymfonyLevelSetList;
use Rector\Symfony\Set\SymfonySetList;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector;

return static function (RectorConfig $rc): void {
  $rc->paths([__DIR__ . '/src']);
  $rc->importNames();
  $rc->skip([
      ReadOnlyPropertyRector::class, // Cannot be used with proxies yet (https://github.com/Ocramius/ProxyManager/issues/737)
      ReturnNeverTypeRector::class, // Not working properly
      ClassPropertyAssignToConstructorPromotionRector::class, // Messes up the annotations
      TypedPropertyRector::class, // Not usable yet, since the serializer has a bug (https://github.com/schmittjoh/serializer/issues/1282)
      ArraySpreadInsteadOfArrayMergeRector::class, // Not very useful, leads to Phan issue
  ]);

  $rc->import(DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES);
  $rc->import(SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES);
  $rc->import(SensiolabsSetList::FRAMEWORK_EXTRA_61);
  $rc->import(LevelSetList::UP_TO_PHP_81);
  $rc->import(SetList::TYPE_DECLARATION_STRICT);
  $rc->import(SymfonyLevelSetList::UP_TO_SYMFONY_60);
  $rc->import(DoctrineSetList::DOCTRINE_CODE_QUALITY);

  $rc->ruleWithConfiguration(AnnotationToAttributeRector::class, [
    // Drenso
      new AnnotationToAttribute(Drenso\Shared\LockableController\UseLock::class),
      new AnnotationToAttribute(Drenso\Shared\FeatureFlags\RequireFeature::class),
    // Doctrine
      new AnnotationToAttribute(Doctrine\ORM\Mapping\AssociationOverrides::class),
      new AnnotationToAttribute(Doctrine\ORM\Mapping\AssociationOverride::class),
    // Symfony missed validator
      new AnnotationToAttribute(Symfony\Component\Validator\Constraints\All::class),
    // Gedmo
      new AnnotationToAttribute(Gedmo\Mapping\Annotation\SoftDeleteable::class),
    // JMS Serializer
      new AnnotationToAttribute(JMS\Serializer\Annotation\Exclude::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\Expose::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\ExclusionPolicy::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\Type::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\Groups::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\VirtualProperty::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\Discriminator::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\SerializedName::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\Accessor::class),
      new AnnotationToAttribute(JMS\Serializer\Annotation\MaxDepth::class),
    // Vich
      new AnnotationToAttribute(Vich\UploaderBundle\Mapping\Annotation\Uploadable::class),
      new AnnotationToAttribute(Vich\UploaderBundle\Mapping\Annotation\UploadableField::class),
    // PhoneNumber
      new AnnotationToAttribute(Misd\PhoneNumberBundle\Validator\Constraints\PhoneNumber::class),
  ]);
};

(I removed a couple of the AnnotationToAttribute that referenced our internal validators, 33 to be precise)

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 17 (11 by maintainers)

Most upvoted comments

Thank you guys for handling this one πŸ‘ I’ll manage release in a couple minutes…

@samsonasik Great work, thank you! Just verified it is also fixed in our pipeline now, and the parallel option now also works like a charm. I would love to see a quick release with this fix!

@jrmcpeek Thanks again for pointing to the parallel option by the way, our pipeline now completes in three minutes instead of 10 πŸ˜„

@bobvandevijver thank you for verify. I am closing it then πŸ˜‰

Yes, this absolutely caused a significant improvement!

real 1m22.219s user 1m20.160s sys 0m1.863s

@TomasVotruba merged πŸ‘

@bobvandevijver could you try latest dev-main and verify if there is speed improvement? Thank you.

composer config minimum-stability dev
composer config prefer-stable true
composer require --dev rector/rector:dev-main

@samsonasik Feel free to merge, if it works well, so we can test it πŸ‘

I created new PR for improvement of BetterNodeFinder::findFirstPrevious() to only lookup of previous of parent when no previous stmt.

@TomasVotruba it possibly related with change by lookup file->getNewStmts() on BetterNodeFinder->findFirstPrevious, which seems make it find all stms over again if not found, which current node itself is hit again by search.

https://github.com/rectorphp/rector-src/commit/e7caae2a5ca85ac9d909f4d66bbad361d72c1482#diff-a658c135f88f0c6bfdd6a0dc7c25761a25747c595ce47a701fb6f7dc2859c74e

from PR: