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

CBG-4032: memory based rev cache implementation #7040

Merged
merged 9 commits into from
Aug 29, 2024
Merged

CBG-4032: memory based rev cache implementation #7040

merged 9 commits into from
Aug 29, 2024

Conversation

gregns1
Copy link
Contributor

@gregns1 gregns1 commented Aug 5, 2024

CBG-4032

Implementation of memory bounded rev cache.
Summary of changes:

  • Added stats for overall rev cache size in bytes
  • This is passed into the rev cache and atomically incremented/decremented as needed
  • Added a function on DocumentRev to calculate the document size based on what we agreed to be measured, channels, revisions and body in bytes.
  • This is called when adding to rev cache for new docs, and after a load from the bucket
  • There is also a version of this for revision deltas
  • Added a representation of a documents size in DocumentRevision and rev cache value, for purposes of passing up and down stack.
  • Create a config value in RevisionCacheOptions to link up to RevCache code for the overall memory limit to be configured on. Temporarily this way, CBG-4134 will finish this side of the work.
  • Left number based eviction where it is. Added a new function for memory based eviction that is called separately after the value is populated with its size + incremented the stat to reflect this.
  • Tests covering each operation on rev cache, eviction and delta caching. In addition have some test coverage of loading from the bucket.
  • For sharded revision cache memory limit, I have copied what we already fo for the number capacity (see NewShardedLRURevisionCache

Pre-review checklist

  • Removed debug logging (fmt.Print, log.Print, ...)
  • Logging sensitive data? Make sure it's tagged (e.g. base.UD(docID), base.MD(dbName))
  • Updated relevant information in the API specifications (such as endpoint descriptions, schemas, ...) in docs/api

Integration Tests

@gregns1 gregns1 marked this pull request as ready for review August 6, 2024 09:45
@adamcfraser adamcfraser assigned adamcfraser and unassigned torcolvin and bbrks Aug 6, 2024
Copy link
Collaborator

@adamcfraser adamcfraser left a comment

Choose a reason for hiding this comment

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

Overall approach seems ok, a few questions/suggestions.

base/stats.go Show resolved Hide resolved
db/revtree.go Outdated Show resolved Hide resolved
db/revtree.go Show resolved Hide resolved
db/crud.go Outdated Show resolved Hide resolved
db/revision_cache_lru.go Outdated Show resolved Hide resolved
db/revision_cache_interface.go Outdated Show resolved Hide resolved
db/revision_cache_interface.go Outdated Show resolved Hide resolved
db/revision_cache_lru.go Outdated Show resolved Hide resolved
db/revision_cache_lru.go Outdated Show resolved Hide resolved
db/revision_cache_lru.go Outdated Show resolved Hide resolved
db/revision.go Outdated Show resolved Hide resolved
db/revision_cache_interface.go Outdated Show resolved Hide resolved
db/revision_cache_interface.go Outdated Show resolved Hide resolved
func (rc *LRURevisionCache) revCacheMemoryBasedEviction() {
// if memory capacity is not set, don't check for eviction this way
if rc.memoryCapacity > 0 && rc.memoryBytes.Value() > rc.memoryCapacity {
rc.performEviction()
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is only going to evict a single value, and there's no guarantee that the evicted value is large enough to offset the incoming value - could end up in a situation where 100 20MB documents trigger the eviction of 100 1k documents, and leave the cache significantly above the memory target.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure I follow. This function is to determine if we need eviction based upon if we have a max size set & the current memory count is above the threshold.
If true it will call performEviction() which acquires the lock and runs a loop for eviction till the memory stat is below the threshold.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This was my mistake - misread performEviction as 'if' instead of 'for'.

@@ -359,6 +388,7 @@ func (value *revCacheValue) asDocumentRevision(delta *RevisionDelta) (DocumentRe
Attachments: value.attachments.ShallowCopy(), // Avoid caller mutating the stored attachments
Deleted: value.deleted,
Removed: value.removed,
MemoryBytes: value.itemBytes,
Copy link
Collaborator

Choose a reason for hiding this comment

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

asDocumentRevision is only intended to copy immutable properties (and so doesn't require callers to hold value.lock.Lock). With the updateDelta handling I don't think itemBytes can be treated as immutable, but it's also important from a performance perspective to not hold the lock.

Copy link
Collaborator

Choose a reason for hiding this comment

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

One option might be to separate the delta and non-delta byte storage on revCacheValue, and compute the sum for DocumentRevision.MemoryBytes here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good spot. I have ended up removing this all together as I can work around this by uisng the getItemBytes() function that acquired read lock to incr/decr the stat wherever necessary.

db/revision_cache_lru.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@adamcfraser adamcfraser left a comment

Choose a reason for hiding this comment

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

I still feel like there is a lot of unnecessary locking of itemBytes in the case where delta sync is not being used (and so itemBytes is immutable), but I'm fine coming back to that based on analysis of the perf results.

@adamcfraser adamcfraser assigned gregns1 and unassigned adamcfraser Aug 29, 2024
@adamcfraser adamcfraser merged commit 9a3f1b8 into main Aug 29, 2024
40 checks passed
@adamcfraser adamcfraser deleted the CBG-4032 branch August 29, 2024 15:48
bbrks pushed a commit that referenced this pull request Sep 26, 2024
* CBG-4032: memory based rev cache implementation

* make test pass with default collection + missing return param

* more issues with default collection test

* touch ups on comment + remove unused function

* updated for review

* further tidy up

* lint fix after refector test

* fixes from rebase

* updates based off review + some more refactoring
gregns1 added a commit that referenced this pull request Sep 27, 2024
* CBG-4023: Removal unmarshalled body on the rev cache (#7030)

* CBG-4135: new stat for rev cache capacity (#7049)

* CBG-4135: new stat for rev cache capacity

* updated based on review

* fix linter

* lint again

* CBG-4032: memory based rev cache implementation (#7040)

* CBG-4032: memory based rev cache implementation

* make test pass with default collection + missing return param

* more issues with default collection test

* touch ups on comment + remove unused function

* updated for review

* further tidy up

* lint fix after refector test

* fixes from rebase

* updates based off review + some more refactoring

* CBG-4134: link rev cache memory limit config option to rev cache (#7084)

* CBG-4134: link rev cache memory limit config option to rev cache

* failing tests

* address commnets

* fix yaml lint

* fix failing test + mistake in docs

Signed-off-by: Gregory Newman-Smith <[email protected]>

---------

Signed-off-by: Gregory Newman-Smith <[email protected]>

* CBG-4234: clean up rev cache work (#7113)

* CBG-4234: clean up rev cache work

* new test

* CBG-4277: Remove unused totalBytesForHistory from getHistory (#7137)

---------

Signed-off-by: Gregory Newman-Smith <[email protected]>
Co-authored-by: Gregory Newman-Smith <[email protected]>
bbrks added a commit that referenced this pull request Oct 8, 2024
* CBG-4023: Removal unmarshalled body on the rev cache (#7030)

* CBG-4135: new stat for rev cache capacity (#7049)

* CBG-4135: new stat for rev cache capacity

* updated based on review

* fix linter

* lint again

* CBG-4032: memory based rev cache implementation (#7040)

* CBG-4032: memory based rev cache implementation

* make test pass with default collection + missing return param

* more issues with default collection test

* touch ups on comment + remove unused function

* updated for review

* further tidy up

* lint fix after refector test

* fixes from rebase

* updates based off review + some more refactoring

* CBG-4134: link rev cache memory limit config option to rev cache (#7084)

* CBG-4134: link rev cache memory limit config option to rev cache

* failing tests

* address commnets

* fix yaml lint

* fix failing test + mistake in docs

Signed-off-by: Gregory Newman-Smith <[email protected]>

---------

Signed-off-by: Gregory Newman-Smith <[email protected]>

* CBG-4234: clean up rev cache work (#7113)

* CBG-4234: clean up rev cache work

* new test

* CBG-4277: Remove unused totalBytesForHistory from getHistory (#7137)

---------

Signed-off-by: Gregory Newman-Smith <[email protected]>
Co-authored-by: Gregory Newman-Smith <[email protected]>
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.

4 participants