Skip to content

Sync FileCacheStorage with changes from phpstan-src - #498

Merged
TomasVotruba merged 14 commits into
rectorphp:mainfrom
staabm:cleanup-file-cache-storage
Jul 26, 2021
Merged

Sync FileCacheStorage with changes from phpstan-src#498
TomasVotruba merged 14 commits into
rectorphp:mainfrom
staabm:cleanup-file-cache-storage

Conversation

@staabm

@staabm staabm commented Jul 23, 2021

Copy link
Copy Markdown
Contributor

as can be seen in #461 (comment) the FileCacheStorage is a major bottleneck while running tests on windows - I guess the same is true on other OSes.

This PR removes unnecessary temp-file handling, because smartFileSystem->dumpFile is already a atomic operation which does magic temp-path file handling behind the scenes. therefore we don't need to do the same things on the rector side.

@TomasVotruba

Copy link
Copy Markdown
Member

Thanks for the PR 👍

Could you share some basic performance comparison before/after? Just so we have an idea how "much"

@staabm

staabm commented Jul 23, 2021

Copy link
Copy Markdown
Contributor Author

I can see a 25-35% perf improvement on my workstation, depending on load.

@TomasVotruba

Copy link
Copy Markdown
Member

Current design is based on cache in PHPStan, and I would like to keep it as close the original to make the maintenance easier. So I want to be sure it has added value, before we change the design.

I've checked the numbers for CI here and in another PR and there is no perf change. Could you demonstrate it in Github Actions I could check?

@staabm

staabm commented Jul 23, 2021

Copy link
Copy Markdown
Contributor Author

Current design is based on cache in PHPStan, and I would like to keep it as close the original to make the maintenance easier

on phpstan side this class evolved already and does no longer use a smartFileSystem. This might also fix the same problem this PR is trying to fix.

I've checked the numbers for CI here and in another PR and there is no perf change.

Also made this observation. I guess the optimization kicks in when doing another run (which doesn‘t happen in CI because we always start from scratch); but might still be usefull for local test runs.

Any idea how to best reproduce CI like performance? Any way to clear all caches or similar?

Could you demonstrate it in Github Actions I could check?

will reproduce on monday when back at the workstation

@TomasVotruba

Copy link
Copy Markdown
Member

on phpstan side this class evolved already and does no longer use a smartFileSystem. This might also fix the same problem this PR is trying to fix.

Could you share the diff?

Any idea how to best reproduce CI like performance? Any way to clear all caches or similar?

I would simply run the CI and compare final times before and after your change. Nothing special.

will reproduce on monday when back at the workstation

👍

@staabm

staabm commented Jul 24, 2021

Copy link
Copy Markdown
Contributor Author

Side idea: maybe it would make sense to have a in-memory CacheStorage for CI to get rid of slow IO

@TomasVotruba

Copy link
Copy Markdown
Member

If the numbers are better, why not :)

@staabm

staabm commented Jul 25, 2021

Copy link
Copy Markdown
Contributor Author

Phpstan upstream version alread contains a CacheInterface and a in-memory impl
https://github.com/phpstan/phpstan-src/tree/master/src/Cache

in other words: using the latest upstream impl should provide everything we need. It seems phpstan even uses this classes internally exactly like proposed

@staabm staabm changed the title Perf optimize FileCacheStorage Sync FileCacheStorage with changes from phpstan-src Jul 26, 2021
@clxmstaab
clxmstaab force-pushed the cleanup-file-cache-storage branch from b6eaf6f to 6823d1a Compare July 26, 2021 07:56
@staabm

staabm commented Jul 26, 2021

Copy link
Copy Markdown
Contributor Author

Current design is based on cache in PHPStan, and I would like to keep it as close the original to make the maintenance easier. So I want to be sure it has added value, before we change the design.

I just updated the implementation to be in line with the phpstan-src upstream FileCacheStorage.

using a in-memory impl to speedup CI is a possible followup.

I would simply run the CI and compare final times before and after your change. Nothing special.

I compared a few builds. the numbers are highly insconsistent, so its pretty hard to tell whether the testsuite is fast/slow because of a change within a PR or whether there is some other external factor which makes the numbers change.

from a logical point of view with the changed FileCacheStorage a lot less file-renaming is going on.
this is also visible from blackfire profiles.


the build is currently failing because of "style" problems:

  ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:29
 ------------------------------------------------------------------------
  - '#"@\\mkdir\(\$directory, 0777\)" is forbidden to use#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:36
 ------------------------------------------------------------------------
  - '#Use custom exceptions instead of native "InvalidArgumentException"#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:47
 ------------------------------------------------------------------------
  - '#Use explicit names over dynamic ones#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:48
 ------------------------------------------------------------------------
  - '#Array destruct is not allowed\. Use value object to pass data instead#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:71
 ------------------------------------------------------------------------
  - '#Array destruct is not allowed\. Use value object to pass data instead#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:77
 ------------------------------------------------------------------------
  - '#"@\\var_export\(new \\Rector\\Caching\\ValueObject\\CacheItem\(\$variableKey, \$data\), \\true\)" is forbidden to use#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:80
 ------------------------------------------------------------------------
  - '#"%s" in sprintf\(\) format must be quoted#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:83
 ------------------------------------------------------------------------
  - '#"@\\rename\(\$tmpPath, \$path\)" is forbidden to use#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:87
 ------------------------------------------------------------------------
  - '#"@\\unlink\(\$tmpPath\)" is forbidden to use#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:89
 ------------------------------------------------------------------------
  - '#Use custom exceptions instead of native "InvalidArgumentException"#'
 ------------------------------------------------------------------------

 ------------------------------------------------------------------------
  packages/Caching/ValueObject/Storage/FileCacheStorage.php:95
 ------------------------------------------------------------------------
  - '#Array destruct is not allowed\. Use value object to pass data instead#'
 ------------------------------------------------------------------------

since you wanted to be in line with phpstan-src I like to ask, which reported problems should be solved (and therefore will create differences between rector-src FileCacheStorage and phpstan-src FileCacheStorage )?

which can/should be phpstan-ignored?

@@ -23,70 +21,83 @@ public function __construct(
) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is the $directory configured which is used? when changing the impl we should add a v2 or similar so persisted cache information does not conflict with the new impl

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this question still relevant or outdated? The original commit had changed

@staabm

staabm commented Jul 26, 2021

Copy link
Copy Markdown
Contributor Author

the adjusted implementation leads to ~200 less rename calls and a 10% speedup (32% of overall the test-runtime is spent on renaming files)

grafik

when running blackfire run --ignore-exit-status .\vendor\bin\phpunit .\packages-tests\

Comment thread packages/Caching/ValueObject/Storage/FileCacheStorage.php
@TomasVotruba

Copy link
Copy Markdown
Member

Could you check last PHPStan fails? I think it's ready then

@staabm

staabm commented Jul 26, 2021

Copy link
Copy Markdown
Contributor Author

@TomasVotruba should be good to go

Comment thread phpstan.neon
return;
}
@\unlink($tmpPath);
if (\DIRECTORY_SEPARATOR === '/' || !\file_exists($path)) {

@samsonasik samsonasik Jul 26, 2021

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you tried in different OS ? DIRECTORY_SEPARATOR is / in macOS:

~ php -a
Interactive shell

php > echo DIRECTORY_SEPARATOR;
/

php > var_dump(\DIRECTORY_SEPARATOR === '/');
bool(true)

Above code will make always throw exception.

@staabm staabm Jul 26, 2021

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this implementation is taken 1:1 from phpstan.

I guess this condition is meant as a non-windows feature detect.
As this class - as is - works in phpstan for months without further bugfixes, I feel this is good enough.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That possibly a dead code then, true || false will result true, true || true will result true, see https://3v4l.org/pKcY1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't tell the details why phpstan has implemented it like that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comment would be useful so we don't use this blindly in the future

@samsonasik

Copy link
Copy Markdown
Member

Unrelated to the PR, could you use same user as PR, eg PR from @clxmstaab use @clxmstaab in commit, or @staabm use @staabm in next PR ?

@staabm

staabm commented Jul 26, 2021

Copy link
Copy Markdown
Contributor Author

Unrelated to the PR, could you use same user as PR, eg PR from @clxmstaab use @clxmstaab in commit, or @staabm use @staabm in next PR ?

I am working on different workstations with different users. why is this "mix" of user/submitter a problem?

In case I could only work from one of these computers my feedback/contribution loop would get longer.

@samsonasik

Copy link
Copy Markdown
Member

I see. Just to make easier to verify that the commit is from the PR author so it can be verified to the commit author if there is something that need to be clarified.

return null;
}
return $cacheItem->getData();
})($key, $variableKey);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very confusing to read. Not sure if args are on left or right.
Could you extract function to assign line and invoke it on 2nd?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its the way how phpstan does this things.

all these nitpicks are great, but it goes against intially mentioned goal:

Current design is based on cache in PHPStan, and I would like to keep it as close the original to make the maintenance easier.

after we apply all 'rector rules' the diff between the phpstan impl and ours here gets bigger and bigger.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, you're right. Let's give it a go

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, I opened a upstream PR to simplify this on phpstan-src

phpstan/phpstan-src#593

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! 👍

This is too much magic for me. I understand only objects and methods :D

* @param string $key
* @param string $variableKey
* @param mixed $data
* @return void

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems these duplicate the PHP code

$firstDirectory = sprintf('%s/%s', $this->directory, Strings::substring($keyHash, 0, 2));
$secondDirectory = sprintf('%s/%s', $firstDirectory, Strings::substring($keyHash, 2, 2));
$firstDirectory = sprintf('%s/%s', $this->directory, substr($keyHash, 0, 2));
$secondDirectory = sprintf('%s/%s', $firstDirectory, substr($keyHash, 2, 2));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@TomasVotruba
TomasVotruba merged commit 6478ec1 into rectorphp:main Jul 26, 2021
@TomasVotruba

Copy link
Copy Markdown
Member

Thank you Marcus 👍

@staabm
staabm deleted the cleanup-file-cache-storage branch July 26, 2021 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants