-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
🔥 Feature: Add max size to cache #1892
Conversation
Thanks for opening this pull request! 🎉 Please check out our contributing guidelines. If you need help or want to chat with us, join us on Discord https://gofiber.io/discord |
Thanks for this feature will review it this weekend and if everything is ok will merge it |
I've just tracked down that one allocation 🥳 Pushing manually (append + heap.Fix) avoids it and performance is now almost on par. Looks kind of tricky though... |
I just remembered that we should use mutex, sync map or atomic due to the concurrency processes to prevent race conditions in the access |
|
Sync is already in place for storage writes, heap modifications happen around it. There shouldn't be any issues |
Before touching docs: are we sure we'll count entries and not bytes? The problem with bytes is that this is only an estimation. We should somehow account for internal values. For example, If the user stores entries in an external storage or the values are just very small, then the internal structures will blow up in size. That value would be an "upper bound on everything" no matter how and where it is stored. |
Perfect |
Will look tomorrow again more closely and answer |
type heapEntry struct { | ||
key string | ||
exp uint64 | ||
bytes uint |
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.
Entry size is stored in the heap to update the total size without reading entries on delete
@dranikpg thx |
Congrats on merging your first pull request! 🎉 We here at Fiber are proud of you! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord |
Add new MaxBytes param to cache docs from gofiber/fiber#1892
* Cache middleware size limit * Replace MaxInt with MaxInt32. Add comments to benchmark * Avoid allocation in heap push. Small fixes * Count body sizes instead of entries * Update cache/readme
This PR is a proposed solution to #1136 and allows limiting the cache size.
As stated in the issue, the cache should expire old entries to make room for new entries. To find old entries, it has to keep track of their expirations in a separate data structure.
Finding a solution
In general, the data structure has to support three main operations:
At first, it looks like a binary search tree would be the perfect fit. However GO's standart library doesn't offer much for implementing them and I didn't want to add new dependencies/piles of code. An easier and equally performant solution exists: lets use a binary heap and track node movements for arbitrary removals. This is what
indexedHeap
is for.Benchmarks
Max size does not affect read performance in any way
Benchmark_Cache_MaxSize
is a benchmark for three cases:My results are as follows:
We're up one allocation from first to second case and about 10% slower per insertion. The third case is the fastest because our cache always stays small.
This is a benchmark where the handler takes zero time to execute. 10% might sound like much, but the difference is less than one microsecond in my case (thats actually suspiciously small 🤔). I doubt any handler call that has to be cached would care about such a time period.
Measuring real memory consumption
Instead of counting entries, we could count their body size to measure real memory consumption.
Other possible soltuions