Skip to content

[Cache] Improve the performance of tag invalidation #44233

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

Closed

Conversation

sbelyshkin
Copy link
Contributor

Q A
Branch? 5.4
Bug fix? no
New feature? no
Deprecations? no
Tickets
License MIT
Doc PR

This PR is a follow-up to #44015.

The change of tag invalidation algorithm has impact on performance because of possible mutual overwrites of tags and calculated values. The degree of impact mainly depends on the number of concurrent processes which access the same keys so the issue is greatly mitigated by LockRegistry in get() and the cache of known tag versions but in case of plain PSR-6 operations, the rate of writes may increase many times.

The main purpose of changeing the algorithm was prevention of tag invalidation losses, and it do its job flawlessly, but for the sake of performance I think we should consider the hybrid algorithm: update tag versions if possible or delete them if the pool rejects updates. It looks like a good compromise to me.

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

Did you run some real world benchs to confirm the issue is not only theoretical?
Because I have one concern, see comment :)

foreach ($tags as $tag) {
\assert('' !== CacheItem::validateKey($tag));
unset($this->knownTagVersions[$tag]);
$ids[] = $tag.static::TAGS_PREFIX;
}

return !$tags || $this->tags->deleteItems($ids);
foreach ($this->tags->getItems($ids) as $tag => $version) {
$tagsToUpdate[$tag] = $version->set($newVersion ?? $newVersion = random_int(\PHP_INT_MIN, \PHP_INT_MAX));
Copy link
Member

Choose a reason for hiding this comment

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

There's an issue with this, which was also existing with the previous strategy but was fixed by always deleting items: unused tags are never removed and will last forever in the DB.

@sbelyshkin
Copy link
Contributor Author

Did you run some real world benchs to confirm the issue is not only theoretical? Because I have one concern, see comment :)

I experimented on my local machine with different configurations for TagAwareAdapter with RedisAdapter and FilesystemAdapter as a backend. I was focused on extra save()s after invalidations so I used the simplest scenario: I run several concurrent processes wich read the same tagged item in the loop for a particular time interval, and 1 process wich periodically invalidated the tag(s). With the get(), I got +2% to the number of save()s; with the getItem(); isHit(); save(); pattern, I got +20% for FS adapter and +5% for Redis; and the worst case was for FS adapter with 0 TTL for known tags: I got +50% to the rate of writes.

TAA+FS+0TTL

TAA+FS+TTL

TAA+Redis+TTL

Surprisingly, the charts show that with non-zero TTL for known tag versions the rate of reads is also increased by ~1%.

@sbelyshkin
Copy link
Contributor Author

sbelyshkin commented Nov 26, 2021

I have to admit I jumped to conclusions. My scenario is much more theoretical than realistic. The fact is that if many processes simultaneously access items with the same tags attached, then on every invalidation you can get overwrites of tag versions which cause recomputation of item values. Theoretically, you can get up to +100% to the number of computations of item values. In real use cases, it is a few percent more write operations and a bit fewer reads, but if tag invalidations happen not often, the difference is negligible.

PS Please do not reference my charts, they represent a very specific scenario that bears no relation to reality.

@fabpot fabpot modified the milestones: 5.4, 6.1 Nov 29, 2021
@sbelyshkin sbelyshkin closed this Dec 27, 2021
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.

5 participants