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

Issue-5320 clean expired cache entries periodically #6392

Merged

Conversation

rudrakhp
Copy link
Contributor

@rudrakhp rudrakhp commented Nov 7, 2023

Why the changes in this PR are needed?

  • Regular clean up of cache entries that have expired for a more efficient use of memory.
  • Removing stale entries regularly will make space for newer entries instead of forcefully evicting entries in a FIFO fashion which happens today. Sometimes entries in front might be long living cache entries (high TTL) that we would rather have in the cache.

What are the changes in this PR?

Two new configurable parameters:

  • inter_query_builtin_cache.forced_eviction_threshold_percentage: By default 100, an integer that denotes the percentage of inter_query_builtin_cache.max_size_bytes that cache usage can grow to before cache will start forcefully evicting entries in a FIFO fashion.
  • inter_query_builtin_cache.stale_entry_eviction_period_seconds: By default 0, an integer that represents the time period in seconds when the stale entry cleanup routine runs.

Notes to assist PR review:

Further comments:

N/A

@rudrakhp rudrakhp changed the title Issue-5320 clean expired cache entries periodically [WIP] Issue-5320 clean expired cache entries periodically Nov 7, 2023
Copy link

netlify bot commented Nov 7, 2023

Deploy Preview for openpolicyagent ready!

Name Link
🔨 Latest commit b3586f4
🔍 Latest deploy log https://app.netlify.com/sites/openpolicyagent/deploys/65975098f357490008ac0c3a
😎 Deploy Preview https://deploy-preview-6392--openpolicyagent.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch 2 times, most recently from 9689d07 to 3a9499d Compare November 8, 2023 11:11
@rudrakhp rudrakhp changed the title [WIP] Issue-5320 clean expired cache entries periodically Issue-5320 clean expired cache entries periodically Nov 8, 2023
@rudrakhp rudrakhp marked this pull request as ready for review November 8, 2023 11:23
topdown/cache/cache.go Outdated Show resolved Hide resolved
topdown/http.go Outdated Show resolved Hide resolved
topdown/cache/cache.go Outdated Show resolved Hide resolved
@anderseknert
Copy link
Member

This is an awesome contribution! Thanks, and keep up the great work! 😃 👏

@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch 2 times, most recently from 500bb33 to cb43b1e Compare November 10, 2023 21:27
@rudrakhp rudrakhp requested a review from lukyer November 10, 2023 21:42
@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch from cb43b1e to ea52d5f Compare November 11, 2023 06:46
@ashutosh-narkar
Copy link
Member

Thanks for the contribution @rudrakhp! I'll review it this week.

@ashutosh-narkar ashutosh-narkar force-pushed the clean_expire_cache_entries branch 2 times, most recently from 8af9e58 to 4d2c1fe Compare November 14, 2023 18:41
Copy link
Member

@ashutosh-narkar ashutosh-narkar left a comment

Choose a reason for hiding this comment

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

@rudrakhp thanks for the contribution. The main comment I have is we need to make changes that are backwards compatible. Some of the API changes you've proposed are not. We can look into introducing a new type if required for the new functionality and think about deprecating the old one.

topdown/cache/cache.go Outdated Show resolved Hide resolved
topdown/cache/cache.go Outdated Show resolved Hide resolved
@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch 2 times, most recently from e1de25d to 381b151 Compare November 18, 2023 06:54
@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch 3 times, most recently from 2619e32 to 36b8968 Compare November 21, 2023 18:12
@ashutosh-narkar ashutosh-narkar requested review from johanfylling and removed request for lukyer December 1, 2023 03:49
johanfylling
johanfylling previously approved these changes Dec 20, 2023
Copy link
Contributor

@johanfylling johanfylling left a comment

Choose a reason for hiding this comment

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

LGTM 👍. Thanks for the contribution 😃!

runtime/runtime.go Outdated Show resolved Hide resolved
topdown/cache/cache.go Show resolved Hide resolved
topdown/cache/cache.go Show resolved Hide resolved
defer ticker.Stop()
for {
select {
case <-ticker.C:
Copy link
Member

Choose a reason for hiding this comment

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

What would happen if we still in the middle of a clean up and ticker ticks? We should probably stop the ticker, do the work and recreate it.

Copy link
Contributor Author

@rudrakhp rudrakhp Dec 21, 2023

Choose a reason for hiding this comment

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

@ashutosh-narkar Only one clean up routine runs at a time, since we listen for more ticker events only after the clean up routine returns. But the time period StaleEntryEvictionPeriodSeconds is enforced between start of each routine. We should reset the ticker if we intend to enforce it between end of previous routine and start of the new one.

We should probably stop the ticker, do the work and recreate it.

SGTM, added changes for the same.

@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch 6 times, most recently from d5f7c13 to 8117bac Compare December 21, 2023 10:51
Copy link
Member

@ashutosh-narkar ashutosh-narkar left a comment

Choose a reason for hiding this comment

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

@rudrakhp this is getting close. Few comments inline 👇 Thanks for working on this.

func NewInterQueryCacheWithContext(ctx context.Context, config *Config) InterQueryCache {
iqCache := newCache(config)
if iqCache.staleEntryEvictionTimePeriodSeconds() > 0 {
iqCache.ticker = time.NewTicker(time.Duration(iqCache.staleEntryEvictionTimePeriodSeconds()) * time.Second)
Copy link
Member

Choose a reason for hiding this comment

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

We don't need to set the ticker on the cache struct. It would be cleaner to just define the ticker locally, then stop the ticker in both the select cases and in case <-iqCache.ticker.C you'd just recreate it after the iqCache.cleanStaleValues() call.

@@ -2159,7 +2159,7 @@ func TestNewInterQueryCacheValue(t *testing.T) {
Body: io.NopCloser(bytes.NewBuffer(b)),
}

result, err := newInterQueryCacheValue(BuiltinContext{}, response, b, &forceCacheParams{})
result, _, err := newInterQueryCacheValue(BuiltinContext{}, response, b, &forceCacheParams{})
Copy link
Member

Choose a reason for hiding this comment

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

It would be good if we add some tests which exercise the new optional params.

Copy link
Contributor Author

@rudrakhp rudrakhp Dec 22, 2023

Choose a reason for hiding this comment

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

@ashutosh-narkar Not sure I got this right, if you are talking about the new cache config params, we have unit tests in cache_test.go exercising them already.
http_tests.go wasn't using the new NewInterQueryCacheWithContext and InsertWithExpiry, have updated it now if that's what you meant. Let me know if there is anything more to test in http_test.go.

Copy link
Member

Choose a reason for hiding this comment

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

I mean in the tests in http_test.go we invoke http.send with its params. I was suggesting to add a case where we call http.send with the new params.

select {
case <-iqCache.ticker.C:
iqCache.cleanStaleValues()
case <-ctx.Done():
Copy link
Member

Choose a reason for hiding this comment

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

A unit test that cancels the context to test this code path would be good.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ashutosh-narkar Can you check the test TestCancelNewInterQueryCacheWithContext already added? Let me know if you think we can test anything more.

@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch 2 times, most recently from ac9a974 to 4595908 Compare December 23, 2023 03:51
@ashutosh-narkar ashutosh-narkar force-pushed the clean_expire_cache_entries branch from 4595908 to b3586f4 Compare January 5, 2024 00:43
Copy link
Member

@ashutosh-narkar ashutosh-narkar left a comment

Choose a reason for hiding this comment

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

@rudrakhp thanks for working on this. Just couple of small comments and then we can get this in. It would be great if you could add an explanation about this change in the commit message body.

if iqCache.staleEntryEvictionTimePeriodSeconds() > 0 {
cleanupTicker := time.NewTicker(time.Duration(iqCache.staleEntryEvictionTimePeriodSeconds()) * time.Second)
go func() {
defer cleanupTicker.Stop()
Copy link
Member

Choose a reason for hiding this comment

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

Nit: We could just move this in the <-ctx.Done() case and avoid the defer statement.

@@ -2159,7 +2159,7 @@ func TestNewInterQueryCacheValue(t *testing.T) {
Body: io.NopCloser(bytes.NewBuffer(b)),
}

result, err := newInterQueryCacheValue(BuiltinContext{}, response, b, &forceCacheParams{})
result, _, err := newInterQueryCacheValue(BuiltinContext{}, response, b, &forceCacheParams{})
Copy link
Member

Choose a reason for hiding this comment

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

I mean in the tests in http_test.go we invoke http.send with its params. I was suggesting to add a case where we call http.send with the new params.

@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch from b3586f4 to 1b7b293 Compare January 9, 2024 18:51
Regularly clean up of cache entries that have expired for a more efficient use of memory.
Introduce two new parameters to tune clean up frequency and threshold for forced FIFO eviction.

Fixes open-policy-agent#5320

Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com>
@rudrakhp rudrakhp force-pushed the clean_expire_cache_entries branch from 1b7b293 to 264ff95 Compare January 9, 2024 19:06
Copy link
Member

@ashutosh-narkar ashutosh-narkar left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks for working on this @rudrakhp!

@ashutosh-narkar ashutosh-narkar merged commit f063c90 into open-policy-agent:main Jan 9, 2024
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve http.send cache cleaning
5 participants