|
|
Subscribe / Log in / New account

mm: improve performance of kernel memory accounting

From:  Roman Gushchin <roman.gushchin-AT-linux.dev>
To:  linux-mm-AT-kvack.org
Subject:  [PATCH rfc 0/5] mm: improve performance of kernel memory accounting
Date:  Wed, 27 Sep 2023 08:08:27 -0700
Message-ID:  <20230927150832.335132-1-roman.gushchin@linux.dev>
Cc:  linux-kernel-AT-vger.kernel.org, cgroups-AT-vger.kernel.org, Johannes Weiner <hannes-AT-cmpxchg.org>, Michal Hocko <mhocko-AT-kernel.org>, Shakeel Butt <shakeelb-AT-google.com>, Muchun Song <muchun.song-AT-linux.dev>, Dennis Zhou <dennis-AT-kernel.org>, Andrew Morton <akpm-AT-linux-foundation.org>, Roman Gushchin <roman.gushchin-AT-linux.dev>
Archive-link:  Article

This patchset improves the performance of the kernel memory accounting by ~30%
as measured by a micro-benchmark [1]. The benchmark is very straightforward:
1M of 64 bytes-large kmalloc() allocations.

Below are results with the disabled kernel memory accounting, the original state
and with this patchset applied.

|             | Kmem disabled | Original | Patched |  Delta |
|-------------+---------------+----------+---------+--------|
| User cgroup |         29764 |    84435 |   59385 | -29.6% |
| Root cgroup |         29742 |    48425 |   31573 | -34.8% |

As we can see, the patchset removes the majority of the overhead when there is
no actual accounting (a task belongs to the root memory cgroup) and almost
halves the accounting overhead. Overall it improves the speed of accounted
allocations by ~30%.

The main idea is to get rid of unnecessary memcg->objcg conversions and switch
to a scope-based protection of objcgs, which eliminates extra operations with
objcg reference counters under a rcu read lock. More details are provided in
individual commit descriptions.

--
[1]:

static int memory_alloc_test(struct seq_file *m, void *v)
{
       unsigned long i, j;
       void **ptrs;
       ktime_t start, end;
       s64 delta, min_delta = LLONG_MAX;

       ptrs = kvmalloc(sizeof(void *) * 1000000, GFP_KERNEL);
       if (!ptrs)
               return -ENOMEM;

       for (j = 0; j < 100; j++) {
               start = ktime_get();
               for (i = 0; i < 1000000; i++)
                       ptrs[i] = kmalloc(64, GFP_KERNEL_ACCOUNT);
               end = ktime_get();

               delta = ktime_us_delta(end, start);
               if (delta < min_delta)
                       min_delta = delta;

               for (i = 0; i < 1000000; i++)
                       kfree(ptrs[i]);
       }

       kvfree(ptrs);
       seq_printf(m, "%lld us\n", min_delta);

       return 0;
}

--

Signed-off-by: Roman Gushchin (Cruise) <roman.gushchin@linux.dev>


Roman Gushchin (5):
  mm: kmem: optimize get_obj_cgroup_from_current()
  mm: kmem: add direct objcg pointer to task_struct
  mm: kmem: make memcg keep a reference to the original objcg
  mm: kmem: scoped objcg protection
  percpu: scoped objcg protection

 include/linux/memcontrol.h |  24 ++++-
 include/linux/sched.h      |   4 +
 mm/memcontrol.c            | 178 ++++++++++++++++++++++++++++++++-----
 mm/percpu.c                |   8 +-
 mm/slab.h                  |  10 +--
 5 files changed, 187 insertions(+), 37 deletions(-)

-- 
2.42.0



Copyright © 2023, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds