Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic/LowerCaseType: improve performance #3839

Closed

Conversation

jrfnl
Copy link
Contributor

@jrfnl jrfnl commented Jun 4, 2023

Description

Someone reported a performance issue with the Generic.PHP.LowerCaseType sniff to me.

Running the Performance report (PR #3810) over a number of codebases, confirmed that the sniff ranked in the top 10 of "slow" sniffs.

As it was, the sniff would examine all variables it comes across and disregard them if they are not properties or not typed. The "disregard when not a property" was done by catching an exception thrown by the File::getMemberProperties() method.

As the majority of T_VARIABLE tokens in the average file are not property declarations, the File::getMemberProperties() method would be triggered lots and lots of times, with the majority of those times resulting in the need for creating and then catching and throwing away the above mentioned exception.

By changing the logic for the sniff to only look within OO constructs and skip over anything non-property, thus avoiding the unnecessary exception creation, I can see a significant difference in the sniff run time.

Using the test file which was originally shared with me and running the below command on PHP 7.4:

phpcs -ps db.php --standard=Generic --report=source -vvv --sniffs=Generic.PHP.LowercaseType

... yielded the following difference in runtime:

Base time:

        *** START SNIFF PROCESSING REPORT ***
        PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseTypeSniff: 0.3802 secs
        *** END SNIFF PROCESSING REPORT ***

Time with the performance tweak included in this PR:

        *** START SNIFF PROCESSING REPORT ***
        PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseTypeSniff: 0.0113 secs
        *** END SNIFF PROCESSING REPORT ***

Using the performance report to benchmark the improvement with a larger number of files, I see improvement across the board as well:

Command used: phpcs -ps . --extensions=php --ignore=/vendor/ --report=performance --standard=psr12

Output for the Generic.PHP.LowercaseType sniff:

Result PHPCS itself Set of Projects A Set of Projects B Set of Projects C
Nr of Files Scanned 614 4115 25546 2250
Before 0.131587 ( 3.9 %) 1.514729 ( 3.0 %) 5.390167 ( 3.4 %) 0.359674 ( 4.2 %)
After 0.029166 ( 0.9 %) 0.449517 ( 0.9 %) 1.917077 ( 1.2 %) 0.181097 ( 2.2 %)

I've also had a quick look at all other PHPCS native sniffs using the File::getMemberProperties() method. As those are all based on the AbstractVariableSniff, they don't seem to suffer from the same issue, or at least, nowhere near as badly.

I also considered changing the setup of the sniff to start using the AbstractVariableSniff, but considering this particular sniff is also examining functions and type casts, I believe that would make the sniff more complex than necessary.

Suggested changelog entry

Generic.PHP.LowercaseType: improved time-to-result for the sniff

Related issues/external references

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
    • This change is only breaking for integrators, not for external standards or end-users.
  • Documentation improvement

@jrfnl
Copy link
Contributor Author

jrfnl commented Jun 4, 2023

This PR will likely conflict with PR #3662 and/or #3833 and either one of those PRs may need rebasing if one of others gets merged first.

@jrfnl jrfnl closed this Jun 4, 2023
@jrfnl jrfnl deleted the feature/generic-lowercasetype-improve-performance branch June 4, 2023 22:02
Someone reported a performance issue with the `Generic.PHP.LowerCaseType` sniff to me.

Running the Performance report (PR 3810) over a number of codebases, confirmed that the sniff ranked in the top 10 of "slow" sniffs.

As it was, the sniff would examine all variables it comes across and disregard them if they are not properties or not typed.
The "disregard when not a property" was done by catching an exception thrown by the `File::getMemberProperties()` method.

As the majority of `T_VARIABLE` tokens in the average file are not property declarations, the `File::getMemberProperties()` method would be triggered lots and lots of times, with the majority of those times resulting in the need for creating and then catching and throwing away the above mentioned exception.

By changing the logic for the sniff to only look within OO constructs and skip over anything non-property, thus avoiding the unnecessary exception creation, I can see a significant difference in the sniff run time.

Using the test file which was originally shared with me and running the below command on PHP 7.4:
```bash
phpcs -ps db.php --standard=Generic --report=source -vvv --sniffs=Generic.PHP.LowercaseType
```

... yielded the following difference in runtime:

Base time:
```
        *** START SNIFF PROCESSING REPORT ***
        PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseTypeSniff: 0.3802 secs
        *** END SNIFF PROCESSING REPORT ***
```

Time with the performance tweak included in this PR:
```
        *** START SNIFF PROCESSING REPORT ***
        PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseTypeSniff: 0.0113 secs
        *** END SNIFF PROCESSING REPORT ***
```

Using the performance report to benchmark the improvement with a larger number of files, I see improvement across the board as well:

Command used: `phpcs -ps . --extensions=php --ignore=/vendor/ --report=performance --standard=psr12`

Output for the `Generic.PHP.LowercaseType` sniff:

Result | PHPCS itself       | Set of Projects A  | Set of Projects B  | Set of Projects C |
------ | ------------------ | ------------------ | ------------------ | ----------------- |
Nr of Files Scanned | 614   | 4115               | 25546              | 2250              |
Before | 0.131587 (  3.9 %) | 1.514729 (  3.0 %) | 5.390167 (  3.4 %) | 0.359674 (  4.2 %)
After  | 0.029166 (  0.9 %) | 0.449517 (  0.9 %) | 1.917077 (  1.2 %) | 0.181097 (  2.2 %)

---

I've also had a quick look at all other PHPCS native sniffs using the `File::getMemberProperties()` method. As those are all based on the `AbstractVariableSniff`, they don't seem to suffer from the same issue, or at least, nowhere near as badly.

I also considered changing the setup of the sniff to start using the `AbstractVariableSniff`, but considering this particular sniff is also examining functions and type casts, I believe that would make the sniff more complex than necessary.
@jrfnl jrfnl restored the feature/generic-lowercasetype-improve-performance branch June 4, 2023 23:24
@jrfnl jrfnl reopened this Jun 4, 2023
@jrfnl jrfnl force-pushed the feature/generic-lowercasetype-improve-performance branch from 3089c41 to a219206 Compare June 4, 2023 23:26
@jrfnl
Copy link
Contributor Author

jrfnl commented Dec 2, 2023

Closing as replaced by PHPCSStandards/PHP_CodeSniffer#63

@jrfnl jrfnl closed this Dec 2, 2023
@jrfnl jrfnl deleted the feature/generic-lowercasetype-improve-performance branch December 2, 2023 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant