Shrinking Caches

shrink_slab is invoked to shrink all caches registered as shrinkable. The allocation mask that specifies the required memory type and the number of pages scanned during page reclaim are passed to the function. Essentially, it iterates over all shrinkers in shrinker_list:

mm/vmscan.c static int shrink_slab(long scanned, unsigned int gfp_mask) {

struct shrinker *shrinker; unsigned long ret = 0;

list_for_each_entry(shrinker, &shrinker_list, list) {

To achieve an even balance between page cache and shrinker cache shrinking, the number of cache elements to be removed is calculated on the basis of the scanned value, which, in turn, is weighted with the seek factor of the cache and the maximum number of elements that can be freed by the current shrinker:

mm/vmscan.c unsigned long long delta; unsigned long total_scan;

unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask);

delta = (4 * scanned) / shrinker->seeks; delta *= max_pass; do_div(delta, lru_pages + 1); shrinker->nr += delta;

By convention, invoking the shrinker function with 0 as argument returns the number of objects in the cache. The kernel also ensures that never more than half the entries in the cache are freed so that no endless loop occurs.

The calculated number of objects to be freed is cumulated in shrinker->nr. Shrinking is triggered as long as this value exceeds the shrink_batch threshold value (typically defined as 128):

mm/vmscan.c total_scan = shrinker->nr; shrinker->nr = 0;

long this_scan = SHRINK_BATCH; int shrink_ret; int nr_before;

nr_before = (*shrinker->shrink)(0, gfp_mask); shrink_ret = (*shrinker->shrink)(this_scan, gfp_mask); if (shrink_ret == -1) break;

if (shrink_ret < nr_before)

ret += nr_before - shrink_ret; mod_page_state(slabs_scanned, this_scan); total_scan -= this_scan;


shrinker->nr += total_scan;

Objects are freed in chunks of 128 to ensure that the system is not blocked for too long. Between each invocation of the shrinker function, cond_resched gives the kernel the opportunity to perform scheduling so that latency does not become too high during cache shrinking.

Continue reading here: Summary

Was this article helpful?

0 0