summaryrefslogtreecommitdiff
path: root/items.c
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2022-08-25 10:17:34 -0700
committerdormando <dormando@rydia.net>2022-08-26 16:35:12 -0700
commit597645db6a2b138710f01ffe5e92e453117b987a (patch)
tree5b7cc7f7b42de79e875836376099ae2d81e100bf /items.c
parente31abc34f990e12efa57218a3b72d38969c6b142 (diff)
downloadmemcached-597645db6a2b138710f01ffe5e92e453117b987a.tar.gz
core: make large item storage more reliable1.6.17
When allocating sub-max chunks for the tail end of a large item the allocator would only look at the exact slab class. If items in a cache are all exclusively large, these slab classes could be empty. Now as a fallback it will also check and evict from the largest slab class even if it doeesn't necessarily want the largest chunk.
Diffstat (limited to 'items.c')
-rw-r--r--items.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/items.c b/items.c
index e5347cc..c526310 100644
--- a/items.c
+++ b/items.c
@@ -226,8 +226,23 @@ item_chunk *do_item_alloc_chunk(item_chunk *ch, const size_t bytes_remain) {
unsigned int id = slabs_clsid(size);
item_chunk *nch = (item_chunk *) do_item_alloc_pull(size, id);
- if (nch == NULL)
- return NULL;
+ if (nch == NULL) {
+ // The final chunk in a large item will attempt to be a more
+ // appropriately sized chunk to minimize memory overhead. However, if
+ // there's no memory available in the lower slab classes we fail the
+ // SET. In these cases as a fallback we ensure we attempt to evict a
+ // max-size item and reuse a large chunk.
+ if (size == settings.slab_chunk_size_max) {
+ return NULL;
+ } else {
+ size = settings.slab_chunk_size_max;
+ id = slabs_clsid(size);
+ nch = (item_chunk *) do_item_alloc_pull(size, id);
+
+ if (nch == NULL)
+ return NULL;
+ }
+ }
// link in.
// ITEM_CHUNK[ED] bits need to be protected by the slabs lock.