[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAJD7tkbY7pCfVTaGVO_jkLz2C8cFie7HW=XbHxWVsLNxF+SaDg@mail.gmail.com>
Date: Fri, 10 Jan 2025 16:21:12 -0800
From: Yosry Ahmed <yosryahmed@...gle.com>
To: James Houghton <jthoughton@...gle.com>
Cc: Sean Christopherson <seanjc@...gle.com>, Paolo Bonzini <pbonzini@...hat.com>,
David Matlack <dmatlack@...gle.com>, David Rientjes <rientjes@...gle.com>, Marc Zyngier <maz@...nel.org>,
Oliver Upton <oliver.upton@...ux.dev>, Wei Xu <weixugc@...gle.com>, Yu Zhao <yuzhao@...gle.com>,
Axel Rasmussen <axelrasmussen@...gle.com>, kvm@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH v8 11/11] KVM: selftests: Add multi-gen LRU aging to access_tracking_perf_test
On Tue, Nov 5, 2024 at 10:49 AM James Houghton <jthoughton@...gle.com> wrote:
>
> This test now has two modes of operation:
> 1. (default) To check how much vCPU performance was affected by access
> tracking (previously existed, now supports MGLRU aging).
> 2. (-p) To also benchmark how fast MGLRU can do aging while vCPUs are
> faulting in memory.
>
> Mode (1) also serves as a way to verify that aging is working properly
> for pages only accessed by KVM. It will fail if one does not have the
> 0x8 lru_gen feature bit.
>
> To support MGLRU, the test creates a memory cgroup, moves itself into
> it, then uses the lru_gen debugfs output to track memory in that cgroup.
> The logic to parse the lru_gen debugfs output has been put into
> selftests/kvm/lib/lru_gen_util.c.
>
> Co-developed-by: Axel Rasmussen <axelrasmussen@...gle.com>
> Signed-off-by: Axel Rasmussen <axelrasmussen@...gle.com>
> Signed-off-by: James Houghton <jthoughton@...gle.com>
> ---
> tools/testing/selftests/kvm/Makefile | 1 +
> .../selftests/kvm/access_tracking_perf_test.c | 366 ++++++++++++++--
> .../selftests/kvm/include/lru_gen_util.h | 55 +++
> .../testing/selftests/kvm/lib/lru_gen_util.c | 391 ++++++++++++++++++
> 4 files changed, 783 insertions(+), 30 deletions(-)
> create mode 100644 tools/testing/selftests/kvm/include/lru_gen_util.h
> create mode 100644 tools/testing/selftests/kvm/lib/lru_gen_util.c
>
> diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
> index f186888f0e00..542548e6e8ba 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -22,6 +22,7 @@ LIBKVM += lib/elf.c
> LIBKVM += lib/guest_modes.c
> LIBKVM += lib/io.c
> LIBKVM += lib/kvm_util.c
> +LIBKVM += lib/lru_gen_util.c
> LIBKVM += lib/memstress.c
> LIBKVM += lib/guest_sprintf.c
> LIBKVM += lib/rbtree.c
> diff --git a/tools/testing/selftests/kvm/access_tracking_perf_test.c b/tools/testing/selftests/kvm/access_tracking_perf_test.c
> index 3c7defd34f56..8d6c2ce4b98a 100644
> --- a/tools/testing/selftests/kvm/access_tracking_perf_test.c
> +++ b/tools/testing/selftests/kvm/access_tracking_perf_test.c
> @@ -38,6 +38,7 @@
> #include <inttypes.h>
> #include <limits.h>
> #include <pthread.h>
> +#include <stdio.h>
> #include <sys/mman.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> @@ -47,6 +48,19 @@
> #include "memstress.h"
> #include "guest_modes.h"
> #include "processor.h"
> +#include "lru_gen_util.h"
> +
> +static const char *TEST_MEMCG_NAME = "access_tracking_perf_test";
> +static const int LRU_GEN_ENABLED = 0x1;
> +static const int LRU_GEN_MM_WALK = 0x2;
> +static const char *CGROUP_PROCS = "cgroup.procs";
> +/*
> + * If using MGLRU, this test assumes a cgroup v2 or cgroup v1 memory hierarchy
> + * is mounted at cgroup_root.
> + *
> + * Can be changed with -r.
> + */
> +static const char *cgroup_root = "/sys/fs/cgroup";
>
> /* Global variable used to synchronize all of the vCPU threads. */
> static int iteration;
> @@ -62,6 +76,9 @@ static enum {
> /* The iteration that was last completed by each vCPU. */
> static int vcpu_last_completed_iteration[KVM_MAX_VCPUS];
>
> +/* The time at which the last iteration was completed */
> +static struct timespec vcpu_last_completed_time[KVM_MAX_VCPUS];
> +
> /* Whether to overlap the regions of memory vCPUs access. */
> static bool overlap_memory_access;
>
> @@ -74,6 +91,12 @@ struct test_params {
>
> /* The number of vCPUs to create in the VM. */
> int nr_vcpus;
> +
> + /* Whether to use lru_gen aging instead of idle page tracking. */
> + bool lru_gen;
> +
> + /* Whether to test the performance of aging itself. */
> + bool benchmark_lru_gen;
> };
>
> static uint64_t pread_uint64(int fd, const char *filename, uint64_t index)
> @@ -89,6 +112,50 @@ static uint64_t pread_uint64(int fd, const char *filename, uint64_t index)
>
> }
>
> +static void write_file_long(const char *path, long v)
> +{
> + FILE *f;
> +
> + f = fopen(path, "w");
> + TEST_ASSERT(f, "fopen(%s) failed", path);
> + TEST_ASSERT(fprintf(f, "%ld\n", v) > 0,
> + "fprintf to %s failed", path);
> + TEST_ASSERT(!fclose(f), "fclose(%s) failed", path);
> +}
> +
> +static char *path_join(const char *parent, const char *child)
> +{
> + char *out = NULL;
> +
> + return asprintf(&out, "%s/%s", parent, child) >= 0 ? out : NULL;
> +}
> +
> +static char *memcg_path(const char *memcg)
> +{
> + return path_join(cgroup_root, memcg);
> +}
> +
> +static char *memcg_file_path(const char *memcg, const char *file)
> +{
> + char *mp = memcg_path(memcg);
> + char *fp;
> +
> + if (!mp)
> + return NULL;
> + fp = path_join(mp, file);
> + free(mp);
> + return fp;
> +}
> +
> +static void move_to_memcg(const char *memcg, pid_t pid)
> +{
> + char *procs = memcg_file_path(memcg, CGROUP_PROCS);
> +
> + TEST_ASSERT(procs, "Failed to construct cgroup.procs path");
> + write_file_long(procs, pid);
> + free(procs);
> +}
> +
>From the peanut gallery, I suspect you can make use of the cgroup
helpers in tools/testing/selftests/cgroup/cgroup_util.h. There are
helpers to locate the cgroup root, create cgroups, enter cgroups, etc.
You can find example uses specifically for memory cgroups (memcgs) in
tools/testing/selftests/cgroup/test_memcontrol.c.
Powered by blists - more mailing lists