Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Add option to MemoryCacheOptions to specify maximum cache entries count #327

Closed
wants to merge 8 commits into from

Conversation

JunTaoLuo
Copy link
Contributor

Addresses #325

// Compact by 10 percent if we exceed the given maximum number of cache entries
if (_entries.Count > _maximumEntriesCount)
{
Compact(0.10);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do this in the background and handle concurrent adds.

@@ -148,6 +150,12 @@ private void SetEntry(CacheEntry entry)
if (entryAdded)
{
entry.AttachTokens();

// Compact by 10 percent if we exceed the given maximum number of cache entries
if (_entries.Count > _maximumEntriesCount)
Copy link
Member

Choose a reason for hiding this comment

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

I assume this always resolves to false for a nullable?

Copy link
Contributor Author

@JunTaoLuo JunTaoLuo Jun 29, 2017

Choose a reason for hiding this comment

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

@@ -13,6 +13,8 @@ public class MemoryCacheOptions : IOptions<MemoryCacheOptions>

public TimeSpan ExpirationScanFrequency { get; set; } = TimeSpan.FromMinutes(1);

public int? EntryCountLimit { get; set; }
Copy link
Member

Choose a reason for hiding this comment

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

doc comment

@JunTaoLuo JunTaoLuo force-pushed the johluo/max-entry-count branch from 1d1622d to ef54a8c Compare June 30, 2017 03:54
{
// Keep compacting until remaining entries are at 90% of maximum
// Stop compacting if no entries were removed, for example if all the remaining entries are pinned with NeverRemove priority
while (Compact(1 - ((0.9 * _entryCountLimit.Value) / _entries.Count)) && _entries.Count > _entryCountLimit.Value) { }
Copy link
Member

Choose a reason for hiding this comment

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

This was triggered by already reaching the max, so why not just ask to compact 10%?

No need for the loop, if it fills up again it will trigger compaction again.

Copy link
Contributor Author

@JunTaoLuo JunTaoLuo Jun 30, 2017

Choose a reason for hiding this comment

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

Stress testing it was failing. For example the test was using two threads to keep adding entries and the removal was not able to keep up. By the time 10% were trimmed, more than 10% were added. So instead, I'm trying to trim until 90% is left and keep doing this until 90% of max is achieved. Hmm some concurrency test are hard to write...

Copy link
Member

Choose a reason for hiding this comment

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

yikes, this loop may never exit and your cache could still keep growing beyond the limit.
plan b: if we're at the limit when you try to add, discard the new item and invoke compaction. This should prevent you from almost ever going over the limit, let alone running to catch up. Make sure to run the normal callbacks for the new item.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In that case, we are no longer trying to remove the least recently used entries. But I suppose that is still better than exceeding the memory limit.

Copy link
Member

Choose a reason for hiding this comment

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

The compaction will try to remove the least recently used to make room for the next guy, but in the meantime add must fail or block, and silent fail is better for a cache.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Trying this now. This gives the extra benefit that the signature of Compact doesn't need to change.

Copy link
Contributor Author

@JunTaoLuo JunTaoLuo Jun 30, 2017

Choose a reason for hiding this comment

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

Seems to work but the behaviour is very strange. When the capacity is hit, the newest item and the oldest items(s) are evicted, whereas I would expect the newest one should be added and only the oldest items are removed. I'll see if there are better alternatives.

@@ -104,6 +105,9 @@ public void CompactWhenMaximumEntriesCountExceeded()

cache.Set("key9", "value9");

// Wait 1 second for compaction to complete
Thread.Sleep(TimeSpan.FromSeconds(1));
Copy link
Member

Choose a reason for hiding this comment

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

register an eviction callback?

@JunTaoLuo
Copy link
Contributor Author

Closed in favour of #332

@JunTaoLuo JunTaoLuo closed this Jul 5, 2017
@JunTaoLuo JunTaoLuo deleted the johluo/max-entry-count branch July 8, 2017 04:21
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants