Skip to content
  • Josef Bacik's avatar
    mm: use sc->priority for slab shrink targets · 9092c71b
    Josef Bacik authored
    Previously we were using the ratio of the number of lru pages scanned to
    the number of eligible lru pages to determine the number of slab objects
    to scan.  The problem with this is that these two things have nothing to
    do with each other, so in slab heavy work loads where there is little to
    no page cache we can end up with the pages scanned being a very low
    number.  This means that we reclaim next to no slab pages and waste a
    lot of time reclaiming small amounts of space.
    
    Consider the following scenario, where we have the following values and
    the rest of the memory usage is in slab
    
      Active:            58840 kB
      Inactive:          46860 kB
    
    Every time we do a get_scan_count() we do this
    
      scan = size >> sc->priority
    
    where sc->priority starts at DEF_PRIORITY, which is 12.  The first loop
    through reclaim would result in a scan target of 2 pages to 11715 total
    inactive pages, and 3 pages to 14710 total active pages.  This is a
    really really small target for a system that is entirely slab pages.
    And this is super optimistic, this assumes we even get to scan these
    pages.  We don't increment sc->nr_scanned unless we 1) isolate the page,
    which assumes it's not in use, and 2) can lock the page.  Under pressure
    these numbers could probably go down, I'm sure there's some random pages
    from daemons that aren't actually in use, so the targets get even
    smaller.
    
    Instead use sc->priority in the same way we use it to determine scan
    amounts for the lru's.  This generally equates to pages.  Consider the
    following
    
      slab_pages = (nr_objects * object_size) / PAGE_SIZE
    
    What we would like to do is
    
      scan = slab_pages >> sc->priority
    
    but we don't know the number of slab pages each shrinker controls, only
    the objects.  However say that theoretically we knew how many pages a
    shrinker controlled, we'd still have to convert this to objects, which
    would look like the following
    
      scan = shrinker_pages >> sc->priority
      scan_objects = (PAGE_SIZE / object_size) * scan
    
    or written another way
    
      scan_objects = (shrinker_pages >> sc->priority) *
    		 (PAGE_SIZE / object_size)
    
    which can thus be written
    
      scan_objects = ((shrinker_pages * PAGE_SIZE) / object_size) >>
    		 sc->priority
    
    which is just
    
      scan_objects = nr_objects >> sc->priority
    
    We don't need to know exactly how many pages each shrinker represents,
    it's objects are all the information we need.  Making this change allows
    us to place an appropriate amount of pressure on the shrinker pools for
    their relative size.
    
    Link: http://lkml.kernel.org/r/1510780549-6812-1-git-send-email-josef@toxicpanda.com
    
    
    Signed-off-by: default avatarJosef Bacik <jbacik@fb.com>
    Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
    Acked-by: default avatarDave Chinner <david@fromorbit.com>
    Acked-by: default avatarAndrey Ryabinin <aryabinin@virtuozzo.com>
    Cc: Michal Hocko <mhocko@kernel.org>
    Cc: Christoph Lameter <cl@linux.com>
    Cc: Pekka Enberg <penberg@kernel.org>
    Cc: David Rientjes <rientjes@google.com>
    Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    9092c71b