From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9674EC5B552 for ; Wed, 4 Jun 2025 18:31:41 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id A0C7E6B0474; Wed, 4 Jun 2025 14:31:38 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 9BD0C8D0007; Wed, 4 Jun 2025 14:31:38 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 8ADB76B0478; Wed, 4 Jun 2025 14:31:38 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 6CC256B0474 for ; Wed, 4 Jun 2025 14:31:38 -0400 (EDT) Received: from smtpin29.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id DC5B6593DB for ; Wed, 4 Jun 2025 18:31:37 +0000 (UTC) X-FDA: 83518561434.29.44D1168 Received: from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254]) by imf01.hostedemail.com (Postfix) with ESMTP id 27C0640018 for ; Wed, 4 Jun 2025 18:31:36 +0000 (UTC) Authentication-Results: imf01.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=HG5ZZg5y; spf=pass (imf01.hostedemail.com: domain of sj@kernel.org designates 172.105.4.254 as permitted sender) smtp.mailfrom=sj@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1749061896; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=3T3NNJCvqAWr50DcflaJH1kOnRPqJG9OmJxO2htoHkQ=; b=WWqD/8CensTCgsoKc7RJ44p9/U04G0UO8cfgqB/AIPb7YuRwoSAzo7+1Ir9uE2kf/DiYf4 OXzmDS3hsASOt0i4PhRy1iqvIJgqwnzRUpf0xGIjaMmc0qrgmTbbA/gtr0ndhQBsrbzhNw Ekb0adjwVuyeOOSoGQVV1GSsddiDiRQ= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1749061896; a=rsa-sha256; cv=none; b=DNPAAPbaoU/sao86vgORYsQc1I4mhoQiMYwL1NmXulKyfuwqPZozp1ElD/Fp9cDWl42Sv/ 0OoV6VgJ5BW/Zym3vGqVQy99wPZPPkKpRprqkNJDruzYyowZDA3ibFwM/mjjQrjOWMCc0/ glsqk/p+W/0e49yuz+zVunbM8qxbT9U= ARC-Authentication-Results: i=1; imf01.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=HG5ZZg5y; spf=pass (imf01.hostedemail.com: domain of sj@kernel.org designates 172.105.4.254 as permitted sender) smtp.mailfrom=sj@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 30D12629F1; Wed, 4 Jun 2025 18:31:35 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id ADBEEC4CEE4; Wed, 4 Jun 2025 18:31:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1749061894; bh=99xhNIYjrRRHYJ4jwFEOfM7WQzxpqK4uF5YCwTKBiUU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HG5ZZg5yjYnEaaix5srRYEyzL36MLTuD9nbxi2c+uLFjCBf7zFxzUa/ftmegZ+/YC bbIGjqGWh2/SoYrwiwNuF8/SXHWzZbt51ZGSQT9F467CDdC8MbWRR3DWgbUzttnS16 6P40rJuqK+3xLyv3dBc2GzQFMxsL2A0T/9gKN2snqOl4whMhBt+AiD8ldGG8G55t/O Rrdnw/hS46mBMDF0SxmdtDGa6LiZQzctEUkWO3F3QENZ1ntWq4ztU7pZmBqbgxu8zc iApOW0H4mGuPfYniatP5oQh+lltr1JoydkgptStbQsTKjIpctqAFruQNvi9ofqNykG JJQUC3RFJIgqw== From: SeongJae Park To: Andrew Morton Cc: SeongJae Park , damon@lists.linux.dev, kernel-team@meta.com, linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH v2 3/4] mm/damon/stat: calculate and expose idle time percentiles Date: Wed, 4 Jun 2025 11:31:26 -0700 Message-Id: <20250604183127.13968-4-sj@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250604183127.13968-1-sj@kernel.org> References: <20250604183127.13968-1-sj@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: 27C0640018 X-Stat-Signature: cz5paxim584qbmzfhocr53efpwb4w1hy X-Rspam-User: X-HE-Tag: 1749061896-638383 X-HE-Meta: U2FsdGVkX18KG53/EayHQeN9ROmyO09Zz7YClfOJzGEf/kDrjOryg6H5ZriM9il0xrg4SMeRInKBC1DUwozQpROju+OYqdy+SkUs/DXR4HTW2oU8CiYXzHe0VB6K8dcpiZvNXAWuflVdyLLTW3GEVkhhc5/eX3IvOu7g2Jj32fDMKSO1lvYhh4CBfJvHv14Gfoue5gD1+sScQm/5d4NLHgT6XeocBhOoklGFoPR2rJ4hONnUZfSU5SGKCOGgiZQ/v59G4KHxTfClhvA5RWGXpj9/0vpjUj20RI/N9m2J1VGfYBkpNyZveixApJGRc1Ix/d04k4nzmV7tM1uRZ4qfwFv779vgQ+79TsCRL8feQyrHG3ql2AFe+4VmzSg8kxlN0MW1rSzRUiyAJajjlXH3HotZ+2g3QKw9+KEI+c8r6lYvGpRVM6BFSYvJplTdIDc5A5YeV4LAfhKeqri09l5oD9zhSwpqfCZrvJAMVSWHVYNkrcVyqFoacMDs7JSV7yZJ1M7jwUyDnDrXbKcsJVRyHwMow5U/SEPqHp6V0kRdbe1mHqmL5QcpPWXBgwBZqCf9YBQTDAqE2C2qe2exLhBLsMurUrIGfBknK5VBuYGH/PsS7tULC3xZ8BlLqcgh8tgYmD9fnnKzqmcunhzUhfmbdIn4LMZ3YP3zxUWF+R1S422OMbBRtN7fZs7oZEgTCqgwXsd2j0EsY3xe/KlITFRibi5N4MftHRfaFHl4wxzeC7NzyPzBClZ0cjJ3eQgaYB4/aTQ7J0hICiT1JdJ6JtZ+DR15RXi96BtVFQtzLtO4HTfqfrkvUv/5UC/DrNhaz67TdvqdUNZl0bHTUpynZN9U79+i+GMZyWkFHMNThdtHHFRHsyuqLcDonr4GW8w7F3wIryH+uhoQUD0ZLcNHKOUbmezIz6q7bbgGSc05DIOjxQFCvibaUDK72YdoLp2N33+kiAlqIE1Gx8HhUhVc5wz 8Eo8kjC2 iB9eW+iP5Ys0OmkvThChNJaTQJKjBCu6ISI9YzbeTecjChZuzYc8CJugV47cqIK/jMTOQiw4sIVrYv+8msyt9yfAYlKoxpaTIeoVubX3Pyc4cvffQIAOuFV8LJDv7kKAcIwEJYeHhIGtIBF7Kk5WRXja+k778r5xLrHsqnlCSVbgao0VGlzUfgIzsSf7nDTVkTEiwjxSVtEgb/tbmNwZ0+ctaKXpnPVwunLulDDc2eY0wniqLbhcQfvFG88n2boyUhIsaVp+7IAaQpOM= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Knowing how much memory is how cold can be useful for understanding coldness and utilization efficiency of memory. The raw form of DAMON's monitoring results has the information. Convert the raw results into the per-byte idle time distributions and expose it as percentiles metric to users, as a read-only DAMON_STAT parameter. In detail, the metrics are calculated as follows. First, DAMON's per-region access frequency and age information is converted into per-byte idle time. If access frequency of a region is higher than zero, every byte of the region has zero idle time. If the access frequency of a region is zero, every byte of the region has idle time as the age of the region. Then the logic sorts the per-byte idle times and provides the value at 0/100, 1/100, ..., 99/100 and 100/100 location of the sorted array. The metric can be easily aggregated and compared on large scale production systems. For example, if an average of 75-th percentile idle time of machines that collected on similar time is two minutes, it means the system's 25 percent memory is not accessed at all for two minutes or more on average. If a workload considers two minutes as unit work time, we can conclude its working set size is only 75 percent of the memory. If the system utilizes proactive reclamation and it supports coldness-based thresholds like DAMON_RECLAIM, the idle time percentiles can be used to find a more safe or aggressive coldness threshold for aimed memory saving. Signed-off-by: SeongJae Park --- mm/damon/stat.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/mm/damon/stat.c b/mm/damon/stat.c index f9ae44db265b..7ef13ea22221 100644 --- a/mm/damon/stat.c +++ b/mm/damon/stat.c @@ -33,6 +33,11 @@ module_param(estimated_memory_bandwidth, ulong, 0400); MODULE_PARM_DESC(estimated_memory_bandwidth, "Estimated memory bandwidth usage in bytes per second"); +static unsigned long memory_idle_ms_percentiles[101] __read_mostly = {0,}; +module_param_array(memory_idle_ms_percentiles, ulong, NULL, 0400); +MODULE_PARM_DESC(memory_idle_ms_percentiles, + "Memory idle time percentiles in milliseconds"); + static struct damon_ctx *damon_stat_context; static void damon_stat_set_estimated_memory_bandwidth(struct damon_ctx *c) @@ -50,6 +55,72 @@ static void damon_stat_set_estimated_memory_bandwidth(struct damon_ctx *c) MSEC_PER_SEC / c->attrs.aggr_interval; } +static unsigned int damon_stat_idletime(const struct damon_region *r) +{ + if (r->nr_accesses) + return 0; + return r->age + 1; +} + +static int damon_stat_cmp_regions(const void *a, const void *b) +{ + const struct damon_region *ra = *(const struct damon_region **)a; + const struct damon_region *rb = *(const struct damon_region **)b; + + return damon_stat_idletime(ra) - damon_stat_idletime(rb); +} + +static int damon_stat_sort_regions(struct damon_ctx *c, + struct damon_region ***sorted_ptr, int *nr_regions_ptr, + unsigned long *total_sz_ptr) +{ + struct damon_target *t; + struct damon_region *r; + struct damon_region **region_pointers; + unsigned int nr_regions = 0; + unsigned long total_sz = 0; + + damon_for_each_target(t, c) { + /* there is only one target */ + region_pointers = kmalloc_array(damon_nr_regions(t), + sizeof(*region_pointers), GFP_KERNEL); + if (!region_pointers) + return -ENOMEM; + damon_for_each_region(r, t) { + region_pointers[nr_regions++] = r; + total_sz += r->ar.end - r->ar.start; + } + } + sort(region_pointers, nr_regions, sizeof(*region_pointers), + damon_stat_cmp_regions, NULL); + *sorted_ptr = region_pointers; + *nr_regions_ptr = nr_regions; + *total_sz_ptr = total_sz; + return 0; +} + +static void damon_stat_set_idletime_percentiles(struct damon_ctx *c) +{ + struct damon_region **sorted_regions, *region; + int nr_regions; + unsigned long total_sz, accounted_bytes = 0; + int err, i, next_percentile = 0; + + err = damon_stat_sort_regions(c, &sorted_regions, &nr_regions, + &total_sz); + if (err) + return; + for (i = 0; i < nr_regions; i++) { + region = sorted_regions[i]; + accounted_bytes += region->ar.end - region->ar.start; + while (next_percentile <= accounted_bytes * 100 / total_sz) + memory_idle_ms_percentiles[next_percentile++] = + damon_stat_idletime(region) * + c->attrs.aggr_interval / USEC_PER_MSEC; + } + kfree(sorted_regions); +} + static int damon_stat_after_aggregation(struct damon_ctx *c) { static unsigned long last_refresh_jiffies; @@ -61,6 +132,7 @@ static int damon_stat_after_aggregation(struct damon_ctx *c) last_refresh_jiffies = jiffies; damon_stat_set_estimated_memory_bandwidth(c); + damon_stat_set_idletime_percentiles(c); return 0; } -- 2.39.5