-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Cache] Add optimized FileSystem & Redis TagAware Adapters #30370
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
Conversation
42588d7
to
eda0753
Compare
src/Symfony/Component/Cache/Adapter/TagAware/FilesystemTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
Thanks for pushing this forward. |
It does make a noticeable difference. If you still want blackfire profile I can look into rebuilding docker env for that, but even just with web debug toolbar; if we take a demo install of eZ Platform EE (v2, Symfony 3.4LTS, dev mode, using server:start), without some other ongoing optimizations:
Those 6078 cache calls results in 17,639 filesystem stat calls:
On Redis the benefit is larger, taking the total time down from 3 to 2 seconds (and further down to <1sec with other optimizations on eZ side), where about 1.5-2 seconds are spent connecting Redis (Redis as a local docker container over TCP using Predis). I expect Redis over network to produce bigger difference. |
eda0753
to
3652282
Compare
Tests added, both optimized TagAware Adapters fail on these:
Edit: I’ll add fixes for those two failures, shouldn’t be to hard, might allow me to cleanup some things here while at it. @nicolas-grekas What are you missing here before this can be moved out of draft besides that? |
b68ec19
to
aeed059
Compare
I'd like to test this PR in my project (currently on 4.2.4). I do not get how to select this PR (what is the branch name??) in my composer.json (or symfony.lock) file. Can you help me ? |
@flaushi 👍you'll need to add something like this in composer.json: {
"repositories": [
{
"type": "vcs",
"url": "https://github.com/andrerom/symfony"
}
],
"require": {
"symfony/symfony": "dev-tagaware_adapters as 4.3.x-dev"
}
} |
@andrerom Any news on this one? How can we move forward? |
d95bf4a
to
8c83bf4
Compare
@fabpot / @nicolas-grekas / @OskarStark Cache tests passing. I found a way to simplify doSave() approach, so this is ready for review from my side now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmaicher, maybe this pull request could be interesting for you!
src/Symfony/Component/Cache/Adapter/TagAware/FilesystemTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
347d6c9
to
d940c07
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's solid work, thanks for digging into the component.
Here are some CS-related comments and then good to merge on my side.
src/Symfony/Component/Cache/Adapter/TagAware/AbstractTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/TagAware/AbstractTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/TagAware/AbstractTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/TagAware/AbstractTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/TagAware/RedisTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/TagAware/RedisTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/TagAware/RedisTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/TagAware/RedisTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/TagAware/FilesystemTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
Thanks for working on this @andrerom, awesome stuff! I'd like to ask for a bit more detail regarding the implementation. So as far as I could see from a quick review, these are additional tag aware adapters alongside the existing
Also in general: I'm not sure about the support for |
@Toflar I can answer your question I think:
The code here is a totally new strategy to store the tags. It does not replace the existing one but completes it when one wants to use it. Both have valid use cases, with advantages and drawbacks.
sure, it shouldn't:
support for predis is already backed into the component since a long time. Messenger is just catching up, and anyway, it's a separate component, with its own need (eg v5) |
Very good, all questions answered. Then it's just a matter of documentation so that people choose the right strategy. I'll happily help out writing them 😄 👍 |
Updated, all review points fixed and back to green. |
2e33716
to
13f0062
Compare
src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/AbstractTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Cache/Adapter/FilesystemTagAwareAdapter.php
Outdated
Show resolved
Hide resolved
@nicolas-grekas two things I'd like to add here:
|
The logic looks great for robustness - there is a missing
would be a contracts break - |
that would be an alternative, and probably cleaner. Any prefs besides what you wrote? |
hmm, silently fail then. Maybe this is a feature request to requirements handling for symfony, to not have to look that up on runtime? |
Doing both :)
The constructor can throw |
ok with the namespace thing as separate PR?
I'd rather not do the requirement check with server lookup on every request, this is why I proposed to align with doClear and do it on demand on call to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lasts comments I suppose :)
src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php
Outdated
Show resolved
Hide resolved
@nicolas-grekas Updated EDIT: Added test for the namespace being seeded by adapter name. |
@@ -46,9 +42,13 @@ protected function __construct(string $namespace = '', int $defaultLifetime = 0) | |||
function ($key, $value, $isHit) use ($defaultLifetime) { | |||
$item = new CacheItem(); | |||
$item->key = $key; | |||
$item->defaultLifetime = $defaultLifetime; | |||
// If structure is in TagAware format, return as is (no value and not a hit) | |||
if (\is_array($value) && \array_key_exists('value', $value)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really unsure about this check: this doesn't look specific enough to me. Not sure we need to do anything IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that we have namespace separation we can drop it
if ($t = $adapter->getTag($this->cachePoolTag)) { | ||
$tags[0] += $t[0]; | ||
} | ||
} | ||
$name = $tags[0]['name'] ?? $id; | ||
if (!isset($tags[0]['namespace'])) { | ||
$tags[0]['namespace'] = $this->getNamespace($seed, $name); | ||
$tags[0]['namespace'] = $this->getNamespace($seed, $name.$class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest a separator here, between the name and the class, just in case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using which character?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a dot :)
96db3cf
to
098a6ea
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just push-forced the fix for my last comments, all good on myside thank you!
098a6ea
to
412167a
Compare
Reduces cache lookups by 50% by changing logic of how tag information is stored to avoid having to look it up on getItem(s) calls. For Filesystem symlinks are used, for Redis "Set" datatype is used.
412167a
to
3278cb1
Compare
Thank you @andrerom. |
…ters (andrerom) This PR was merged into the 4.3-dev branch. Discussion ---------- [Cache] Add optimized FileSystem & Redis TagAware Adapters | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes _TODO: src/**/CHANGELOG.md_ | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #28250 | License | MIT | Doc PR | symfony/symfony-docs#... TODO Reduces cache lookups by 50% when using TagAware, by changing logic of how tag information is stored to avoid having to look it up on getItem(s) calls. For Filesystem symlinks are used, for Redis "Set" datatype is used. Commits ------- 3278cb1 [Cache] Add optimized FileSystem & Redis TagAware Adapters
Just to make clear, to be able to run this code on Platform.sh (eZ Cloud/Symfony Cloud) you have following options:
|
@SerheyDolgushev It's needed for sPOP support which was added in 3.1.3: https://github.com/symfony/symfony/pull/30370/files#diff-410efc18de675a67676caaf96a22be12R174 So this, and Redis 3.2+ is a hard requirement for the RedisTagAwareAdapter. If you are not able to get platform.sh to update the extension they use on PHP 7.1-72, then either use PHP 7.3, predis or FileSystemTagAwareAdapte (skip this option if you run cluster like Platform.sh Enterprise PE-6+. Professional and PE-[X]XL however is fine as they only run one web server at a time). Do you see anything that could have been more clear in the exception to make this even more clear? |
Reduces cache lookups by 50% when using TagAware, by changing logic of how tag information is stored to avoid having to look it up on getItem(s) calls.
For Filesystem symlinks are used, for Redis "Set" datatype is used.