From: SeongJae Park <hidden> Date: 2021-07-20 13:15:32
From: SeongJae Park <redacted>
NOTE: This is only an RFC for future features of DAMON patchset[1], which is
not merged in the mainline yet. The aim of this RFC is to show how DAMON would
be evolved once it is merged in. So, if you have some interest here, please
consider reviewing the DAMON patchset, either.
[1] https://lore.kernel.org/linux-mm/20210716081449.22187-1-sj38.park@gmail.com/
Changes from Previous Version (RFC v2)
======================================
Compared to the RFC v2
(https://lore.kernel.org/linux-mm/20210608115254.11930-1-sj38.park@gmail.com/),
this version contains below changes.
- Rebase on latest -mm tree (v5.14-rc1-mmots-2021-07-15-18-47)
- Implement a time quota (limits the time for trying reclamation of cold pages)
- Make reclamation restarts from exactly the point it stopped due to the limit
Introduction
============
In short, this patchset 1) makes the engine for general data access
pattern-oriented memory management be useful for production environments, and
2) implements a static kernel module for lightweight proactive reclamation
using the engine.
Proactive Reclamation
---------------------
On general memory over-committed systems, proactively reclaiming cold pages
helps saving memory and reducing latency spikes that incurred by the direct
reclaim or the CPU consumption of kswapd, while incurring only minimal
performance degradation[2].
Particularly, a Free Pages Reporting[9] based memory over-commit virtualization
system would be one of such use cases. In the system, the guest VMs reports
their free memory to host, and the host reallocates the reported memory to
other guests. As a result, the system's memory can be fully utilized.
However, the guests could be not so memory-frugal, mainly because some kernel
subsystems and user-space applications are designed to use as much memory as
available. Then, guests would report only small amount of free memory to host,
and results in poor memory utilization. Running the proactive reclamation in
guests could help mitigating this problem.
Google has implemented the general idea and using it in their data center.
They further proposed upstreaming it in LSFMM'19, and "the general consensus
was that, while this sort of proactive reclaim would be useful for a number of
users, the cost of this particular solution was too high to consider merging it
upstream"[3]. The cost mainly comes from the coldness tracking. Roughly
speaking, the implementation periodically scans the 'Accessed' bit of each
page. For the reason, the overhead linearly increases as the size of the
memory and the scanning frequency grows. As a result, Google is known to
dedicating one CPU for the work. That's a reasonable option to someone like
Google, but it wouldn't be so to some others.
DAMON and DAMOS: An engine for data access pattern-oriented memory management
-----------------------------------------------------------------------------
DAMON[4] is a framework for general data access monitoring. Its adaptive
monitoring overhead control feature minimizes its monitoring overhead. It also
let the upper-bounded of the overhead be configurable by clients, regardless of
the size of the monitoring target memory. While monitoring 70 GB memory of a
production system every 5 milliseconds, it consumes less than 1% single CPU
time. For this, it could sacrify some of the quality of the monitoring
results. Nevertheless, the lower-bound of the quality is configurable, and it
uses a best-effort algorithm for better quality. Our test results[5] show the
quality is practical enough. From the production system monitoring, we were
able to find a 4 KB region in the 70 GB memory that shows highest access
frequency. For people having different requirements, the features can
selectively turned off, and DAMON supports the page-granularity monitoring[6],
though it makes the overhead higher and proportional to the memory size again.
We normally don't monitor the data access pattern just for fun but to improve
something like memory management. Proactive reclamation is one such usage.
For such general cases, DAMON provides a feature called DAMon-based Operation
Schemes (DAMOS)[7]. It makes DAMON an engine for general data access pattern
oriented memory management. Using this, clients can ask DAMON to find memory
regions of specific data access pattern and apply some memory management action
(e.g., page out, move to head of the LRU list, use huge page, ...). We call
the request 'scheme'.
Proactive Reclamation on top of DAMON/DAMOS
-------------------------------------------
Therefore, by using DAMON for the cold pages detection, the proactive
reclamation's monitoring overhead issue could be solved. If someone like
Google is ok to dedicate some CPUs for the monitoring and wants
page-granularity monitoring, they can configure DAMON so.
Actually, we previously implemented a version of proactive reclamation using
DAMOS and achieved noticeable improvements with our evaluation setup[5].
Nevertheless, it was only for a proof-of-concept. It supports only virtual
address spaces of processes, and require additional tuning efforts for given
workloads and the hardware. For the tuning, we recently introduced a simple
auto-tuning user space tool[8]. Google is also known to using a ML-based
similar approach for their fleets[2]. But, making it just works in the kernel
would be more convenient for general users.
To this end, this patchset improves DAMOS to be ready for such production
usages, and implements another version of the proactive reclamation, namely
DAMON_RECLAIM, on top of it.
DAMOS Improvements: Speed Limit, Prioritization, and Watermarks
---------------------------------------------------------------
First of all, the current version of DAMOS supports only virtual address
spaces. This patchset makes it supports the physical address space for the
page out action.
One major problem of the current version of DAMOS is the lack of the
aggressiveness control, which can results in arbitrary overhead. For example,
if huge memory regions having the data access pattern of interest are found,
applying the requested action to all of the regions could incur significant
overhead. It can be controlled by modifying the target data access pattern
with manual or automated approaches[2,8]. But, some people would prefer the
kernel to just work with only intuitive tuning or default values.
For this, this patchset implements a safeguard time/size quota. Using this,
the clients can specify up to how much time can be used for applying the
action, and/or up to how much memory regions the action can be applied within
specific time duration. A followup question is, to which memory regions should
the action applied within the limits? We implement a simple regions
prioritization mechanism for each action and make DAMOS to apply the action to
high priority regions first. It also allows clients tune the prioritization
mechanism to use different weights for region's size, access frequency, and
age. This means we could use not only LRU but also LFU or some fancy
algorithms like CAR[10] with lightweight overhead.
Though DAMON is lightweight, someone would want to remove even the overhead
when it is unnecessary. Currently, it should manually turned on and off by
clients, but some clients would simply want to turn it on and off based on some
metrics like free memory ratio or memory fragmentation. For such cases, this
patchset implements a watermarks-based automatic activation feature. It allows
the clients configure the metric of their interest, and three watermarks of the
metric. If the metric is higher than the high watermark or lower than the low
watermark, the scheme is deactivated. If the metric is lower than the mid
watermark but higher than the low watermark, the scheme is activated.
DAMON-based Reclaim
-------------------
Using the improved DAMOS, this patchset implements a static kernel module
called 'damon_reclaim'. It finds memory regions that didn't accessed for
specific time duration and page out. Consuming too much CPU for the paging out
operations, or invoking it too frequently can be critical for systems
configuring its swap devices with software-defined in-memory block devices like
zram or total number of writes limited devices like SSDs, respectively. To
avoid the problems, the time and/or size quotas can be configured. Under the
quotas, it pages out memory regions that didn't accessed longer first. Also,
to remove the monitoring overhead under peaceful situation, and to fall back to
the LRU-list based page granularity reclamation when it doesn't make progress,
the three watermarks based activation mechanism is used, with the free memory
ratio as the watermark metric.
For convenient configurations, it provides several module parameters. Using
these, sysadmins can enable/disable it and tune the coldness identification
time threshold, the time/size quotas, and the three watermarks. In detail,
sysadmins can use the kernel command line for a boot time tuning, or the sysfs
('/sys/modules/damon_reclaimparameters/') for overriding those in runtime.
Evaluation
==========
In short, DAMON_RECLAIM on v5.13 Linux kernel with ZRAM swap device and 50ms/s
time quota achieves 40.34% memory saving with only 3.38% runtime overhead. For
this, DAMON_RECLAIM consumes only 5.16% of single CPU time. Among the CPU
consumption, only up to about 1.448% of single CPU time is expected to be used
for the access pattern monitoring.
Setup
-----
We evaluate DAMON_RECLAIM to show how each of the DAMOS improvements make
effect. For this, we measure entire system memory footprint and runtime of 24
realistic workloads in PARSEC3 and SPLASH-2X benchmark suites on my QEMU/KVM
based virtual machine. The virtual machine runs on an i3.metal AWS instance
and has 130GiB memory. It also utilizes a 4 GiB ZRAM swap device. We do the
measurement 5 times and use averages. We also measure the CPU consumption of
DAMON_RECLAIM.
Detailed Results
----------------
The result numbers are shown in below table.
DAMON_RECLAIM without the speed limit achieves 47.16% memory saving, but incur
5.4% runtime slowdown to the workloads on average. For this, DAMON_RECLAIM
consumes about 11.62% single CPU time.
Applying 10ms/s, 50ms/s, and 200ms/s time quotas without the regions
prioritization reduces the slowdown to 2.51%, 4.53%, and 4.69%, respectively.
DAMON_RECLAIM's CPU utilization also similarly reduced: 1.78%, 5.7%, and 10.92%
of single CPU time. That is, the overhead is proportional to the speed limit.
Nevertheless, it also reduces the memory saving because it becomes less
aggressive. In detail, the three variants show 4.55%, 40.84%, and 48.42%
memory saving, respectively.
Applying the regions prioritization (page out regions that not accessed longer
first within the time quota) further reduces the performance degradation.
Runtime slowdowns has been 2.51% -> 1.84% (10ms/s), 4.53% -> 3.38% (50ms/s), and
4.69% -> 5.1% (200ms/s). Interestingly, prioritization also reduced memory
saving a little bit. I think that's because already paged out regions are
prioritized again.
time quota prioritization memory_saving cpu_util slowdown
N N 47.16% 11.62% 5.4%
10ms/s N 4.55% 1.78% 2.51%
50ms/s N 40.84% 5.7% 4.53%
200ms/s N 48.42% 10.92% 4.69%
10ms/s Y 0.77% 1.37% 1.84%
50ms/s Y 40.34% 5.16% 3.38%
200ms/s Y 47.99% 10.41% 5.1%
Baseline and Complete Git Trees
===============================
The patches are based on the latest -mm tree (v5.14-rc1-mmots-2021-07-15-18-47)
plus DAMON patchset[1], DAMOS patchset[7], and physical address space support
patchset[6]. You can also clone the complete git tree from:
$ git clone git://github.com/sjp38/linux -b damon_reclaim/rfc/v3
The web is also available:
https://github.com/sjp38/linux/releases/tag/damon_reclaim/rfc/v3
Development Trees
-----------------
There are a couple of trees for entire DAMON patchset series and
features for future release.
- For latest release: https://github.com/sjp38/linux/tree/damon/master
- For next release: https://github.com/sjp38/linux/tree/damon/next
Long-term Support Trees
-----------------------
For people who want to test DAMON patchset series but using only LTS kernels,
there are another couple of trees based on two latest LTS kernels respectively
and containing the 'damon/master' backports.
- For v5.4.y: https://github.com/sjp38/linux/tree/damon/for-v5.4.y
- For v5.10.y: https://github.com/sjp38/linux/tree/damon/for-v5.10.y
Sequence Of Patches
===================
The first patch makes DAMOS to support the physical address space for the page
out action. Following five patches (patches 2-6) implement the time/size
quotas. Next four patches (patches 7-10) implement the memory regions
prioritization within the limit. Then, three following patches (patches 11-13)
implement the watermarks-based schemes activation. Finally, the last two
patches (patches 14-15) implement and document the DAMON-based reclamation on
top of the advanced DAMOS.
[1] https://lore.kernel.org/linux-mm/20210716081449.22187-1-sj38.park@gmail.com/
[2] https://research.google/pubs/pub48551/
[3] https://lwn.net/Articles/787611/
[4] https://damonitor.github.io
[5] https://damonitor.github.io/doc/html/latest/vm/damon/eval.html
[6] https://lore.kernel.org/linux-mm/20201216094221.11898-1-sjpark@amazon.com/
[7] https://lore.kernel.org/linux-mm/20201216084404.23183-1-sjpark@amazon.com/
[8] https://github.com/awslabs/damoos
[9] https://www.kernel.org/doc/html/latest/vm/free_page_reporting.html
[10] https://www.usenix.org/conference/fast-04/car-clock-adaptive-replacement
Patch History
=============
Changes from RFC v2
(https://lore.kernel.org/linux-mm/20210608115254.11930-1-sj38.park@gmail.com/)
- Rebase on latest -mm tree (v5.14-rc1-mmots-2021-07-15-18-47)
- Make reclamation restarts from exactly the point it stopped due to the limit
- Implement a time quota (limits the time for trying reclamation of cold pages)
[1] https://lore.kernel.org/linux-mm/20210716081449.22187-1-sj38.park@gmail.com/
Changes from RFC v1
(https://lore.kernel.org/linux-mm/20210531133816.12689-1-sj38.park@gmail.com/)
- Avoid fake I/O load reporting (James Gowans)
- Remove kernel configs for the build time enabling and the parameters setting
- Export kdamond pid via a readonly parameter file
- Elaborate coverletter, especially for evaluation and DAMON_RECLAIM interface
- Add documentation
- Rebase on -mm tree
- Cleanup code
SeongJae Park (15):
mm/damon/paddr: Support the pageout scheme
mm/damon/damos: Make schemes aggressiveness controllable
damon/core/schemes: Skip already charged targets and regions
mm/damon/schemes: Implement time quota
mm/damon/dbgfs: Support schemes' time/IO quotas
mm/damon/selftests: Support schemes quotas
mm/damon/schemes: Prioritize regions within the quotas
mm/damon/vaddr,paddr: Support pageout prioritization
mm/damon/dbgfs: Support prioritization weights
tools/selftests/damon: Update for regions prioritization of schemes
mm/damon/schemes: Activate schemes based on a watermarks mechanism
mm/damon/dbgfs: Support watermarks
selftests/damon: Support watermarks
mm/damon: Introduce DAMON-based reclamation
Documentation/admin-guide/mm/damon: Add a document for DAMON_RECLAIM
Documentation/admin-guide/mm/damon/index.rst | 1 +
.../admin-guide/mm/damon/reclaim.rst | 233 ++++++++++++
include/linux/damon.h | 136 ++++++-
mm/damon/Kconfig | 12 +
mm/damon/Makefile | 1 +
mm/damon/core.c | 283 +++++++++++++-
mm/damon/dbgfs.c | 47 ++-
mm/damon/paddr.c | 52 ++-
mm/damon/prmtv-common.c | 48 ++-
mm/damon/prmtv-common.h | 5 +
mm/damon/reclaim.c | 354 ++++++++++++++++++
mm/damon/vaddr.c | 15 +
.../testing/selftests/damon/debugfs_attrs.sh | 4 +-
13 files changed, 1163 insertions(+), 28 deletions(-)
create mode 100644 Documentation/admin-guide/mm/damon/reclaim.rst
create mode 100644 mm/damon/reclaim.c
--
2.17.1
From: SeongJae Park <hidden> Date: 2021-07-20 13:15:53
From: SeongJae Park <redacted>
If there are too large memory regions fulfilling the target data access
pattern of a DAMON-based operation scheme, applying the action of the
scheme could consume too much CPU. To avoid that, this commit
implements a limit for the action application speed. Using the feature,
the client can set up to how much amount of memory regions the action
could applied within specific time duration.
Signed-off-by: SeongJae Park <redacted>
---
include/linux/damon.h | 36 +++++++++++++++++++++++---
mm/damon/core.c | 60 +++++++++++++++++++++++++++++++++++++------
mm/damon/dbgfs.c | 4 ++-
3 files changed, 87 insertions(+), 13 deletions(-)
@@ -89,6 +89,26 @@ enum damos_action {DAMOS_STAT,/* Do nothing but only record the stat */};+/**+*structdamos_quota-Controlstheaggressivenessofthegivenscheme.+*@sz:Maximumbytesofmemorythattheactioncanbeapplied.+*@reset_interval:Chargeresetintervalinmilliseconds.+*+*ToavoidconsumingtoomuchCPUtimeorIOresourcesforapplyingthe+*&structdamos->actiontolargememory,DAMONallowsuserstosetasize+*quota.Thequotacanbesetbywritingnon-zerovaluesto&sz.Ifthesize+*quotaisset,DAMONtriestoapplytheactiononlyupto&szbyteswithin+*&reset_interval.+*/+structdamos_quota{+unsignedlongsz;+unsignedlongreset_interval;++/* private: For charging the quota */+unsignedlongcharged_sz;+unsignedlongcharged_from;+};+/***structdamos-RepresentsaDataAccessMonitoring-basedOperationScheme.*@min_sz_region:Minimumsizeoftargetregions.
From: SeongJae Park <hidden> Date: 2021-07-20 13:16:24
From: SeongJae Park <redacted>
This commit makes the DAMON primitives for physical address space to
support the pageout action for DAMON-based Operation Schemes. IOW, now
the users can implement their own data access-aware reclamations for
whole system using DAMOS.
Signed-off-by: SeongJae Park <redacted>
---
mm/damon/paddr.c | 38 +++++++++++++++++++++++++++++++++++++-
mm/damon/prmtv-common.c | 2 +-
mm/damon/prmtv-common.h | 2 ++
3 files changed, 40 insertions(+), 2 deletions(-)
@@ -18,6 +18,8 @@/* Get a random number in [l, r) */#define damon_rand(l, r) (l + prandom_u32_max(r - l))+structpage*damon_get_page(unsignedlongpfn);+voiddamon_va_mkold(structmm_struct*mm,unsignedlongaddr);booldamon_va_young(structmm_struct*mm,unsignedlongaddr,unsignedlong*page_sz);
From: SeongJae Park <hidden> Date: 2021-07-20 13:17:06
From: SeongJae Park <redacted>
This commit makes the default monitoring primitives for virtual address
spaces and the physical address sapce to support memory regions
prioritization for 'PAGEOUT' DAMOS action. It calculates hotness of
each region as weighted sum of 'nr_accesses' and 'age' of the region and
get the priority score as reverse of the hotness, so that cold regions
can be paged out first.
Signed-off-by: SeongJae Park <redacted>
---
include/linux/damon.h | 4 ++++
mm/damon/paddr.c | 14 +++++++++++++
mm/damon/prmtv-common.c | 46 +++++++++++++++++++++++++++++++++++++++++
mm/damon/prmtv-common.h | 3 +++
mm/damon/vaddr.c | 15 ++++++++++++++
5 files changed, 82 insertions(+)
@@ -236,3 +236,49 @@ bool damon_pa_young(unsigned long paddr, unsigned long *page_sz)*page_sz=result.page_sz;returnresult.accessed;}++#define DAMON_MAX_SUBSCORE (100)+#define DAMON_MAX_AGE_IN_LOG (32)++intdamon_pageout_score(structdamon_ctx*c,structdamon_region*r,+structdamos*s)+{+unsignedintmax_nr_accesses;+intfreq_subscore;+unsignedintage_in_sec;+intage_in_log,age_subscore;+unsignedintfreq_weight=s->quota.weight_nr_accesses;+unsignedintage_weight=s->quota.weight_age;+inthotness;++max_nr_accesses=c->aggr_interval/c->sample_interval;+freq_subscore=r->nr_accesses*DAMON_MAX_SUBSCORE/max_nr_accesses;++age_in_sec=(unsignedlong)r->age*c->aggr_interval/1000000;+for(age_in_log=0;age_in_log<DAMON_MAX_AGE_IN_LOG&&age_in_sec;+age_in_log++,age_in_sec>>=1)+;++/* If frequency is 0, higher age means it's colder */+if(freq_subscore==0)+age_in_log*=-1;++/*+*Nowage_in_logisin[-DAMON_MAX_AGE_IN_LOG,DAMON_MAX_AGE_IN_LOG].+*Scaleittobein[0,100]andsetitasagesubscore.+*/+age_in_log+=DAMON_MAX_AGE_IN_LOG;+age_subscore=age_in_log*DAMON_MAX_SUBSCORE/+DAMON_MAX_AGE_IN_LOG/2;++hotness=(freq_weight*freq_subscore+age_weight*age_subscore);+if(freq_weight+age_weight)+hotness/=freq_weight+age_weight;+/*+*Transformittofitin[0,DAMOS_MAX_SCORE]+*/+hotness=hotness*DAMOS_MAX_SCORE/DAMON_MAX_SUBSCORE;++/* Return coldness of the region */+returnDAMOS_MAX_SCORE-hotness;+}
From: SeongJae Park <hidden> Date: 2021-07-20 13:19:17
From: SeongJae Park <redacted>
This commit updates DAMON selftests for 'schemes' debugfs file to
reflect the changes in the format.
Signed-off-by: SeongJae Park <redacted>
---
tools/testing/selftests/damon/debugfs_attrs.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -0,0 +1,233 @@+.. SPDX-License-Identifier: GPL-2.0++=======================+DAMON-based Reclamation+=======================++DAMON-based Reclamation (DAMON_RECLAIM) is a static kernel module that aimed to+be used for proactive and lightweight reclamation under light memory pressure.+It doesn't aim to replace the LRU-list based page_granularity reclamation, but+to be selectively used for different level of memory pressure and requirements.++Where Proactive Reclamation is Required?+========================================++On general memory over-committed systems, proactively reclaiming cold pages+helps saving memory and reducing latency spikes that incurred by the direct+reclaim of the process or CPU consumption of kswapd, while incurring only+minimal performance degradation [1]_[2]_ .++Free Pages Reporting [3]_ based memory over-commit virtualization systems are+good example of the cases. In such systems, the guest VMs reports their free+memory to host, and the host reallocates the reported memory to other guests.+As a result, the memory of the systems are fully utilized. However, the+guests could be not so memory-frugal, mainly because some kernel subsystems and+user-space applications are designed to use as much memory as available. Then,+guests could report only small amount of memory as free to host, results in+memory utilization drop of the systems. Running the proactive reclamation in+guests could mitigate this problem.++How It Works?+=============++DAMON_RECLAIM finds memory regions that didn't accessed for specific time+duration and page out. To avoid it consuming too much CPU for the paging out+operation, a speed limit can be configured. Under the speed limit, it pages+out memory regions that didn't accessed longer time first. System+administrators can also configure under what situation this scheme should+automatically activated and deactivated with three memory pressure watermarks.++Interface: Module Parameters+============================++To use this feature, you should first ensure your system is running on a kernel+that is built with ``CONFIG_DAMON_RECLAIM=y``.++To let sysadmins enable or disable it and tune for the given system,+DAMON_RECLAIM utilizes module parameters. That is, you can put+``damon_reclaim.<parameter>=<value>`` on the kernel boot command line or write+proper values to ``/sys/modules/damon_reclaim/parameters/<parameter>`` files.++Note that the parameter values except ``enabled`` are applied only when+DAMON_RECLAIM starts. Therefore, if you want to apply new parameter values in+runtime and DAMON_RECLAIM is already enabled, you should disable and re-enable+it via ``enabled`` parameter file. Writing of the new values to proper+parameter values should be done before the re-enablement.++Below are the description of each parameter.++enabled+-------++Enable or disable DAMON_RECLAIM.++You can enable DAMON_RCLAIM by setting the value of this parameter as ``Y``.+Setting it as ``N`` disables DAMON_RECLAIM. Note that DAMON_RECLAIM could do+no real monitoring and reclamation due to the watermarks-based activation+condition. Refer to below descriptions for the watermarks parameter for this.++min_age+-------++Time threshold for cold memory regions identification in microseconds.++If a memory region is not accessed for this or longer time, DAMON_RECLAIM+identifies the region as cold, and reclaims it.++quota_ms+--------++Limit of time for the reclamation in milliseconds.++DAMON_RECLAIM tries to use only up to this time within a time window+(quota_reset_interval_ms) for trying reclamation of cold pages. This can be+used for limiting CPU consumption of DAMON_RECLAIM. If the value is zero, the+limit is disabled.++100 ms by default.++quota_sz+--------++Limit of size of memory for the reclamation in bytes.++DAMON_RECLAIM charges amount of memory which it tried to reclaim within a time+window (quota_reset_interval_ms) and makes no more than this limit is tried.+This can be used for limiting consumption of CPU and IO. If this value is+zero, the limit is disabled.++1 GiB by default.++quota_reset_interval_ms+-----------------------++The time/size quota charge reset interval in milliseconds.++The charget reset interval for the quota of time (quota_ms) and size+(quota_sz). That is, DAMON_RECLAIM does not try reclamation for more than+quota_ms milliseconds or quota_sz bytes within quota_reset_interval_ms+milliseconds.++1 second by default.++wmarks_interval+---------------++Minimal time to wait before checking the watermarks, when DAMON_RECLAIM is+enabled but inactive due to its watermarks rule.++wmarks_high+-----------++Free memory rate (per thousand) for the high watermark.++If free memory of the system in bytes per thousand bytes is higher than this,+DAMON_RECLAIM becomes inactive, so it does nothing but only periodically checks+the watermarks.++wmarks_mid+----------++Free memory rate (per thousand) for the middle watermark.++If free memory of the system in bytes per thousand bytes is between this and+the low watermark, DAMON_RECLAIM becomes active, so starts the monitoring and+the reclaiming.++wmarks_low+----------++Free memory rate (per thousand) for the low watermark.++If free memory of the system in bytes per thousand bytes is lower than this,+DAMON_RECLAIM becomes inactive, so it does nothing but periodically checks the+watermarks. In the case, the system falls back to the LRU-list based page+granularity reclamation logic.++sample_interval+---------------++Sampling interval for the monitoring in microseconds.++The sampling interval of DAMON for the cold memory monitoring. Please refer to+the DAMON documentation (:doc:`usage`) for more detail.++aggr_interval+-------------++Aggregation interval for the monitoring in microseconds.++The aggregation interval of DAMON for the cold memory monitoring. Please+refer to the DAMON documentation (:doc:`usage`) for more detail.++min_nr_regions+--------------++Minimum number of monitoring regions.++The minimal number of monitoring regions of DAMON for the cold memory+monitoring. This can be used to set lower-bound of the monitoring quality.+But, setting this too high could result in increased monitoring overhead.+Please refer to the DAMON documentation (:doc:`usage`) for more detail.++max_nr_regions+--------------++Maximum number of monitoring regions.++The maximum number of monitoring regions of DAMON for the cold memory+monitoring. This can be used to set upper-bound of the monitoring overhead.+However, setting this too low could result in bad monitoring quality. Please+refer to the DAMON documentation (:doc:`usage`) for more detail.++monitor_region_start+--------------------++Start of target memory region in physical address.++The start physical address of memory region that DAMON_RECLAIM will do work+against. That is, DAMON_RECLAIM will find cold memory regions in this region+and reclaims. By default, biggest System RAM is used as the region.++monitor_region_end+------------------++End of target memory region in physical address.++The end physical address of memory region that DAMON_RECLAIM will do work+against. That is, DAMON_RECLAIM will find cold memory regions in this region+and reclaims. By default, biggest System RAM is used as the region.++kdamond_pid+-----------++PID of the DAMON thread.++If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread. Else,+-1.++Example+=======++Below runtime example commands make DAMON_RECLAIM to find memory regions that+not accessed for 30 seconds or more and pages out. The reclamation is limited+to be done only up to 1 GiB per second to avoid DAMON_RECLAIM consuming too+much CPU time for the paging out operation. It also asks DAMON_RECLAIM to do+nothing if the system's free memory rate is more than 50%, but start the real+works if it becomes lower than 40%. If DAMON_RECLAIM doesn't make progress and+therefore the free memory rate becomes lower than 20%, it asks DAMON_RECLAIM to+do nothing again, so that we can fall back to the LRU-list based page+granularity reclamation. ::++ # cd /sys/modules/damon_reclaim/parameters+ # echo 30000000 > min_age+ # echo $((1 * 1024 * 1024 * 1024)) > quota_sz+ # echo 1000 > quota_reset_interval_ms+ # echo 500 > wmarks_high+ # echo 400 > wmarks_mid+ # echo 200 > wmarks_low+ # echo Y > enabled++..[1] https://research.google/pubs/pub48551/+..[2] https://lwn.net/Articles/787611/+..[3] https://www.kernel.org/doc/html/latest/vm/free_page_reporting.html
From: SeongJae Park <hidden> Date: 2021-07-20 13:21:56
From: SeongJae Park <redacted>
This commit implements a new kernel subsystem that finds cold memory
regions using DAMON and reclaims those immediately. It is intended to
be used as proactive lightweigh reclamation logic for light memory
pressure. For heavy memory pressure, it could be inactivated and fall
back to the traditional page-scanning based reclamation.
It's implemented on top of DAMON framework to use the DAMON-based
Operation Schemes (DAMOS) feature. It utilizes all the DAMOS features
including speed limit, prioritization, and watermarks.
It could be enabled and tuned in build time via the kernel
configuration, in boot time via the kernel boot parameter, and in run
time via its module parameter ('/sys/module/damon_reclaim/parameters/')
interface.
Signed-off-by: SeongJae Park <redacted>
---
mm/damon/Kconfig | 12 ++
mm/damon/Makefile | 1 +
mm/damon/reclaim.c | 354 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 367 insertions(+)
create mode 100644 mm/damon/reclaim.c
@@ -0,0 +1,354 @@+// SPDX-License-Identifier: GPL-2.0+/*+*DAMON-basedpagereclamation+*+*Author:SeongJaePark<sjpark@amazon.de>+*/++#define pr_fmt(fmt) "damon-reclaim: " fmt++#include<linux/damon.h>+#include<linux/ioport.h>+#include<linux/module.h>+#include<linux/sched.h>+#include<linux/workqueue.h>++#ifdef MODULE_PARAM_PREFIX+#undef MODULE_PARAM_PREFIX+#endif+#define MODULE_PARAM_PREFIX "damon_reclaim."++/*+*EnableordisableDAMON_RECLAIM.+*+*YoucanenableDAMON_RCLAIMbysettingthevalueofthisparameteras``Y``.+*Settingitas``N``disablesDAMON_RECLAIM.NotethatDAMON_RECLAIMcould+*donorealmonitoringandreclamationduetothewatermarks-basedactivation+*condition.Refertobelowdescriptionsforthewatermarksparameterfor+*this.+*/+staticboolenabled__read_mostly;+module_param(enabled,bool,0600);++/*+*Timethresholdforcoldmemoryregionsidentificationinmicroseconds.+*+*Ifamemoryregionisnotaccessedforthisorlongertime,DAMON_RECLAIM+*identifiestheregionascold,andreclaims.5secondsbydefault.+*/+staticunsignedlongmin_age__read_mostly=5000000;+module_param(min_age,ulong,0600);++/*+*Limitoftimefortryingthereclamationinmilliseconds.+*+*DAMON_RECLAIMtriestouseonlyuptothistimewithinatimewindow+*(quota_reset_interval_ms)fortryingreclamationofcoldpages.Thiscanbe+*usedforlimitingCPUconsumptionofDAMON_RECLAIM.Ifthevalueiszero,+*thelimitisdisabled.+*+*100msbydefault.+*/+staticunsignedlongquota_ms__read_mostly=100;+module_param(quota_ms,ulong,0600);++/*+*Limitofsizeofmemoryforthereclamationinbytes.+*+*DAMON_RECLAIMchargesamountofmemorywhichittriedtoreclaimwithina+*timewindow(quota_reset_interval_ms)andmakesnomorethanthislimitis+*tried.ThiscanbeusedforlimitingconsumptionofCPUandIO.Ifthis+*valueiszero,thelimitisdisabled.+*+*1GiBbydefault.+*/+staticunsignedlongquota_sz__read_mostly=1024*1024*1024;+module_param(quota_sz,ulong,0600);++/*+*Thetime/sizequotachargeresetintervalinmilliseconds.+*+*Thechargeresetintervalforthequotaoftime(quota_ms)andsize+*(quota_sz).Thatis,DAMON_RECLAIMdoesnottryreclamationformorethan+*quota_msmillisecondsorquota_szbyteswithinquota_reset_interval_ms+*milliseconds.+*+*1secondbydefault.+*/+staticunsignedlongquota_reset_interval_ms__read_mostly=1000;+module_param(quota_reset_interval_ms,ulong,0600);++/*+*Thewatermarkschecktimeintervalinmicroseconds.+*+*Minimaltimetowaitbeforecheckingthewatermarks,whenDAMON_RECLAIMis+*enabledbutinactiveduetoitswatermarksrule.5secondsbydefault.+*/+staticunsignedlongwmarks_interval__read_mostly=5000000;+module_param(wmarks_interval,ulong,0600);++/*+*Freememoryrate(perthousand)forthehighwatermark.+*+*Iffreememoryofthesysteminbytesperthousandbytesishigherthan+*this,DAMON_RECLAIMbecomesinactive,soitdoesnothingbutperiodically+*checksthewatermarks.500(50%)bydefault.+*/+staticunsignedlongwmarks_high__read_mostly=500;+module_param(wmarks_high,ulong,0600);++/*+*Freememoryrate(perthousand)forthemiddlewatermark.+*+*Iffreememoryofthesysteminbytesperthousandbytesisbetweenthisand+*thelowwatermark,DAMON_RECLAIMbecomesactive,sostartsthemonitoring+*andthereclaiming.400(40%)bydefault.+*/+staticunsignedlongwmarks_mid__read_mostly=400;+module_param(wmarks_mid,ulong,0600);++/*+*Freememoryrate(perthousand)forthelowwatermark.+*+*Iffreememoryofthesysteminbytesperthousandbytesislowerthanthis,+*DAMON_RECLAIMbecomesinactive,soitdoesnothingbutperiodicallychecks+*thewatermarks.Inthecase,thesystemfallsbacktotheLRU-basedpage+*granularityreclamationlogic.200(20%)bydefault.+*/+staticunsignedlongwmarks_low__read_mostly=200;+module_param(wmarks_low,ulong,0600);++/*+*Samplingintervalforthemonitoringinmicroseconds.+*+*ThesamplingintervalofDAMONforthecoldmemorymonitoring.Pleaserefer+*totheDAMONdocumentationformoredetail.5msbydefault.+*/+staticunsignedlongsample_interval__read_mostly=5000;+module_param(sample_interval,ulong,0600);++/*+*Aggregationintervalforthemonitoringinmicroseconds.+*+*TheaggregationintervalofDAMONforthecoldmemorymonitoring.Please+*refertotheDAMONdocumentationformoredetail.100msbydefault.+*/+staticunsignedlongaggr_interval__read_mostly=100000;+module_param(aggr_interval,ulong,0600);++/*+*Minimumnumberofmonitoringregions.+*+*TheminimalnumberofmonitoringregionsofDAMONforthecoldmemory+*monitoring.Thiscanbeusedtosetlower-boundofthemonitoringquality.+*But,settingthistoohighcouldresultinincreasedmonitoringoverhead.+*PleaserefertotheDAMONdocumentationformoredetail.10bydefault.+*/+staticunsignedlongmin_nr_regions__read_mostly=10;+module_param(min_nr_regions,ulong,0600);++/*+*Maximumnumberofmonitoringregions.+*+*ThemaximumnumberofmonitoringregionsofDAMONforthecoldmemory+*monitoring.Thiscanbeusedtosetupper-boundofthemonitoringoverhead.+*However,settingthistoolowcouldresultinbadmonitoringquality.+*PleaserefertotheDAMONdocumentationformoredetail.1000bydefault.+*/+staticunsignedlongmax_nr_regions__read_mostly=1000;+module_param(max_nr_regions,ulong,0600);++/*+*Startofthetargetmemoryregioninphysicaladdress.+*+*ThestartphysicaladdressofmemoryregionthatDAMON_RECLAIMwilldowork+*against.Bydefault,biggestSystemRAMisusedastheregion.+*/+staticunsignedlongmonitor_region_start__read_mostly;+module_param(monitor_region_start,ulong,0600);++/*+*Endofthetargetmemoryregioninphysicaladdress.+*+*TheendphysicaladdressofmemoryregionthatDAMON_RECLAIMwilldowork+*against.Bydefault,biggestSystemRAMisusedastheregion.+*/+staticunsignedlongmonitor_region_end__read_mostly;+module_param(monitor_region_end,ulong,0600);++/*+*PIDoftheDAMONthread+*+*IfDAMON_RECLAIMisenabled,thisbecomesthePIDoftheworkerthread.+*Else,-1.+*/+staticintkdamond_pid__read_mostly=-1;+module_param(kdamond_pid,int,0400);++staticstructdamon_ctx*ctx;+staticstructdamon_target*target;++structdamon_reclaim_ram_walk_arg{+unsignedlongstart;+unsignedlongend;+};++staticintwalk_system_ram(structresource*res,void*arg)+{+structdamon_reclaim_ram_walk_arg*a=arg;++if(a->end-a->start<res->end-res->start){+a->start=res->start;+a->end=res->end;+}+return0;+}++/*+*Findbiggest'SystemRAM'resourceandstoreitsstartandendaddressin+*@startand@end,respectively.IfnoSystemRAMisfound,returnsfalse.+*/+staticboolget_monitoring_region(unsignedlong*start,unsignedlong*end)+{+structdamon_reclaim_ram_walk_argarg={};++walk_system_ram_res(0,ULONG_MAX,&arg,walk_system_ram);+if(arg.end<=arg.start)+returnfalse;++*start=arg.start;+*end=arg.end;+returntrue;+}++staticstructdamos*damon_reclaim_new_scheme(void)+{+structdamos_watermarkswmarks={+.metric=DAMOS_WMARK_FREE_MEM_RATE,+.interval=wmarks_interval,+.high=wmarks_high,+.mid=wmarks_mid,+.low=wmarks_low,+};+structdamos_quotaquota={+/*+*Donottryreclamationformorethanquota_msmilliseconds+*orquota_szbyteswithinquota_reset_interval_ms.+*/+.ms=quota_ms,+.sz=quota_sz,+.reset_interval=quota_reset_interval_ms,+/* Within the quota, page out older regions first. */+.weight_sz=0,+.weight_nr_accesses=0,+.weight_age=1+};+structdamos*scheme=damon_new_scheme(+/* Find regions having PAGE_SIZE or larger size */+PAGE_SIZE,ULONG_MAX,+/* and not accessed at all */+0,0,+/* for min_age or more micro-seconds, and */+min_age/aggr_interval,UINT_MAX,+/* page out those, as soon as found */+DAMOS_PAGEOUT,+/* under the quota. */+"a,+/* (De)activate this according to the watermarks. */+&wmarks);++returnscheme;+}++staticintdamon_reclaim_turn(boolon)+{+structdamon_region*region;+structdamos*scheme;+interr;++if(!on){+err=damon_stop(&ctx,1);+if(!err)+kdamond_pid=-1;+returnerr;+}++err=damon_set_attrs(ctx,sample_interval,aggr_interval,0,+min_nr_regions,max_nr_regions);+if(err)+returnerr;++if(monitor_region_start>monitor_region_end)+return-EINVAL;+if(!monitor_region_start&&!monitor_region_end&&+!get_monitoring_region(&monitor_region_start,+&monitor_region_end))+return-EINVAL;+/* DAMON will free this on its own when finish monitoring */+region=damon_new_region(monitor_region_start,monitor_region_end);+if(!region)+return-ENOMEM;+damon_add_region(region,target);++/* Will be freed by 'damon_set_schemes()' below */+scheme=damon_reclaim_new_scheme();+if(!scheme)+gotofree_region_out;+err=damon_set_schemes(ctx,&scheme,1);+if(err)+gotofree_scheme_out;++err=damon_start(&ctx,1);+if(!err){+kdamond_pid=ctx->kdamond->pid;+return0;+}++free_scheme_out:+damon_destroy_scheme(scheme);+free_region_out:+damon_destroy_region(region,target);+returnerr;+}++#define ENABLE_CHECK_INTERVAL_MS 1000+staticstructdelayed_workdamon_reclaim_timer;+staticvoiddamon_reclaim_timer_fn(structwork_struct*work)+{+staticboollast_enabled;+boolnow_enabled;++now_enabled=enabled;+if(last_enabled!=now_enabled){+if(!damon_reclaim_turn(now_enabled))+last_enabled=now_enabled;+else+enabled=last_enabled;+}++schedule_delayed_work(&damon_reclaim_timer,+msecs_to_jiffies(ENABLE_CHECK_INTERVAL_MS));+}+staticDECLARE_DELAYED_WORK(damon_reclaim_timer,damon_reclaim_timer_fn);++staticint__initdamon_reclaim_init(void)+{+ctx=damon_new_ctx(DAMON_ADAPTIVE_TARGET);+if(!ctx)+return-ENOMEM;++damon_pa_set_primitives(ctx);++/* 4242 means nothing but fun */+target=damon_new_target(4242);+if(!target){+damon_destroy_ctx(ctx);+return-ENOMEM;+}+damon_add_target(ctx,target);++schedule_delayed_work(&damon_reclaim_timer,0);+return0;+}++module_init(damon_reclaim_init);
From: SeongJae Park <hidden> Date: 2021-07-20 13:21:56
From: SeongJae Park <redacted>
This commit updates DAMON debugfs interface to support the watermarks
based schemes activation. For this, now 'schemes' file receives five
more values.
Signed-off-by: SeongJae Park <redacted>
---
mm/damon/dbgfs.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
From: SeongJae Park <hidden> Date: 2021-07-20 13:21:56
From: SeongJae Park <redacted>
This commit updates the DAMON selftests for 'schemes' debugfs file, as
the file format is updated.
Signed-off-by: SeongJae Park <redacted>
---
tools/testing/selftests/damon/debugfs_attrs.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: SeongJae Park <hidden> Date: 2021-07-20 13:21:56
From: SeongJae Park <redacted>
DAMON-based operation schemes need to be manually turned on and off. In
some use cases, however, the condition for turning a scheme on and off
would depend on the system's situation. For example, schemes for
proactive pages reclamation would need to be turned on when some memory
pressure is detected, and turned off when the system has enough free
memory.
For easier control of schemes activation based on the system situation,
this commit introduces a watermarks-based mechanism. The client can
describe the watermark metric (e.g., amount of free memory in the
system), watermark check interval, and three watermarks, namely high,
mid, and low. If the scheme is deactivated, it only gets the metric and
compare that to the three watermarks for every check interval. If the
metric is higher than the high watermark, the scheme is deactivated. If
the metric is between the mid watermark and the low watermark, the
scheme is activated. If the metric is lower than the low watermark, the
scheme is deactivated again. This is to allow users fall back to
traditional page-granularity mechanisms.
Signed-off-by: SeongJae Park <redacted>
---
include/linux/damon.h | 52 ++++++++++++++++++++++-
mm/damon/core.c | 97 ++++++++++++++++++++++++++++++++++++++++++-
mm/damon/dbgfs.c | 5 ++-
3 files changed, 151 insertions(+), 3 deletions(-)
@@ -932,6 +947,83 @@ static bool kdamond_need_stop(struct damon_ctx *ctx)returntrue;}+staticunsignedlongdamos_wmark_metric_value(enumdamos_wmark_metricmetric)+{+structsysinfoi;++switch(metric){+caseDAMOS_WMARK_FREE_MEM_RATE:+si_meminfo(&i);+returni.freeram*1000/i.totalram;+default:+break;+}+return-EINVAL;+}++/*+*Returnszeroiftheschemeisactive.Else,returnstimetowaitfornext+*watermarkcheckinmicro-seconds.+*/+staticunsignedlongdamos_wmark_wait_us(structdamos*scheme)+{+unsignedlongmetric;++if(scheme->wmarks.metric==DAMOS_WMARK_NONE)+return0;++metric=damos_wmark_metric_value(scheme->wmarks.metric);+/* higher than high watermark or lower than low watermark */+if(metric>scheme->wmarks.high||scheme->wmarks.low>metric){+if(scheme->wmarks.activated)+pr_info("inactivate a scheme (%d) for %s wmark\n",+scheme->action,+metric>scheme->wmarks.high?+"high":"low");+scheme->wmarks.activated=false;+returnscheme->wmarks.interval;+}++/* inactive and higher than middle watermark */+if((scheme->wmarks.high>=metric&&metric>=scheme->wmarks.mid)&&+!scheme->wmarks.activated)+returnscheme->wmarks.interval;++if(!scheme->wmarks.activated)+pr_info("activate a scheme (%d)\n",scheme->action);+scheme->wmarks.activated=true;+return0;+}++staticvoidkdamond_usleep(unsignedlongusecs)+{+if(usecs>100*1000)+schedule_timeout_interruptible(usecs_to_jiffies(usecs));+else+usleep_range(usecs,usecs+1);+}++/* Returns negative error code if it's not activated but should return */+staticintkdamond_wait_activation(structdamon_ctx*ctx)+{+structdamos*s;+unsignedlongwait_time;+unsignedlongmin_wait_time=0;++while(!kdamond_need_stop(ctx)){+damon_for_each_scheme(s,ctx){+wait_time=damos_wmark_wait_us(s);+if(!min_wait_time||wait_time<min_wait_time)+min_wait_time=wait_time;+}+if(!min_wait_time)+return0;++kdamond_usleep(min_wait_time);+}+return-EBUSY;+}+staticvoidset_kdamond_stop(structdamon_ctx*ctx){mutex_lock(&ctx->kdamond_lock);
@@ -962,6 +1054,9 @@ static int kdamond_fn(void *data)sz_limit=damon_region_sz_limit(ctx);while(!kdamond_need_stop(ctx)){+if(kdamond_wait_activation(ctx))+continue;+if(ctx->primitive.prepare_access_checks)ctx->primitive.prepare_access_checks(ctx);if(ctx->callback.after_sampling&&
From: SeongJae Park <hidden> Date: 2021-07-20 13:22:08
From: SeongJae Park <redacted>
This commit allows DAMON debugfs interface users set the prioritization
weights by putting three more numbers to the 'schemes' file.
Signed-off-by: SeongJae Park <redacted>
---
mm/damon/dbgfs.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
From: SeongJae Park <hidden> Date: 2021-07-20 13:22:21
From: SeongJae Park <redacted>
This commit updates DAMON selftests to support updated schemes debugfs
file format for the quotas.
Signed-off-by: SeongJae Park <redacted>
---
tools/testing/selftests/damon/debugfs_attrs.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: SeongJae Park <hidden> Date: 2021-07-20 13:24:35
From: SeongJae Park <redacted>
This commit makes DAMON to apply schemes to regions having higher
priority first, if it cannot apply schemes to all regions due to the
quotas.
The prioritization function should be implemented in each monitoring
primitive. Those would commonly calculate the priority of the region
using attributes of regions, namely 'size', 'nr_accesses', and 'age'.
For example, some primitive would calculate the priority of each region
using a weighted sum of 'nr_accesses' and 'age' of the region.
The optimal weights would depend on give environments, so this commit
allows it to be customizable. Nevertheless, the score calculation
functions are only encouraged to respect the weights, not mandated. So,
the customization might not work for some primitives.
Signed-off-by: SeongJae Park <redacted>
---
include/linux/damon.h | 26 ++++++++++++++++++
mm/damon/core.c | 62 ++++++++++++++++++++++++++++++++++++++-----
2 files changed, 81 insertions(+), 7 deletions(-)
@@ -14,6 +14,8 @@/* Minimal region size. Every damon_region is aligned by this. */#define DAMON_MIN_REGION PAGE_SIZE+/* Max priority score for DAMON-based operation schemes */+#define DAMOS_MAX_SCORE (99)/***structdamon_addr_range-Representsanaddressregionof[@start,@end).
@@ -679,6 +701,32 @@ static void kdamond_apply_schemes(struct damon_ctx *c)quota->charged_sz=0;damos_set_effective_quota(quota);}++if(!c->primitive.get_scheme_score)+continue;++/* Fill up the score histogram */+memset(quota->histogram,0,sizeof(quota->histogram));+damon_for_each_target(t,c){+damon_for_each_region(r,t){+if(!__damos_valid_target(r,s))+continue;+score=c->primitive.get_scheme_score(+c,t,r,s);+quota->histogram[score]+=+r->ar.end-r->ar.start;+if(score>max_score)+max_score=score;+}+}++/* Set the min score limit */+for(cumulated_sz=0,score=max_score;;score--){+cumulated_sz+=quota->histogram[score];+if(cumulated_sz>=quota->esz||!score)+break;+}+quota->min_score=score;}damon_for_each_target(t,c){
From: SeongJae Park <hidden> Date: 2021-07-20 13:28:51
From: SeongJae Park <redacted>
This commit makes the debugfs interface of DAMON to support the schemes'
time/IO quotas by chaning the format of the input for the schemes file.
Signed-off-by: SeongJae Park <redacted>
---
mm/damon/dbgfs.c | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)
From: SeongJae Park <hidden> Date: 2021-07-20 13:30:55
From: SeongJae Park <redacted>
If DAMOS stopped applying action to memory regions due to the speed
limit, it does nothing until next charge window starts. Then, it starts
the work from the beginning of the address space. If there is a huge
memory region at the beginning of the address space and it fulfills the
scheme target data access pattern, the action will applied to only the
region.
This commit mitigates the case by skipping memory regions that charged
in previous charge window at the beginning of current charge window.
Signed-off-by: SeongJae Park <redacted>
---
include/linux/damon.h | 5 +++++
mm/damon/core.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
From: SeongJae Park <hidden> Date: 2021-07-20 13:30:55
From: SeongJae Park <redacted>
This commit implements time-based quota for DAMON-based Operation
Schemes. If the quota is set, DAMOS tries to use only up to the
user-defined quota within the 'reset_interval' milliseconds.
Signed-off-by: SeongJae Park <redacted>
---
include/linux/damon.h | 25 +++++++++++++++++++-----
mm/damon/core.c | 45 ++++++++++++++++++++++++++++++++++++++-----
2 files changed, 60 insertions(+), 10 deletions(-)
@@ -91,20 +91,35 @@ enum damos_action {/***structdamos_quota-Controlstheaggressivenessofthegivenscheme.+*@ms:Maximummillisecondsthattheschemecanuse.*@sz:Maximumbytesofmemorythattheactioncanbeapplied.*@reset_interval:Chargeresetintervalinmilliseconds.**ToavoidconsumingtoomuchCPUtimeorIOresourcesforapplyingthe-*&structdamos->actiontolargememory,DAMONallowsuserstosetasize-*quota.Thequotacanbesetbywritingnon-zerovaluesto&sz.Ifthesize-*quotaisset,DAMONtriestoapplytheactiononlyupto&szbyteswithin-*&reset_interval.+*&structdamos->actiontolargememory,DAMONallowsuserstosettimeand/or+*sizequotas.Thequotascanbesetbywritingnon-zerovaluesto&msand+*&sz,respectively.Ifthetimequotaisset,DAMONtriestouseonlyupto+*&msmillisecondswithin&reset_intervalforapplyingtheaction.Ifthe+*sizequotaisset,DAMONtriestoapplytheactiononlyupto&szbytes+*within&reset_interval.+*+*Internally,thetimequotaistransformedtoasizequotausingestimated+*throughputofthescheme'saction.DAMONthencomparesitagainst&szand+*usessmalleroneastheeffectivequota.*/structdamos_quota{+unsignedlongms;unsignedlongsz;unsignedlongreset_interval;-/* private: For charging the quota */+/* private: */+/* For throughput estimation */+unsignedlongtotal_charged_sz;+unsignedlongtotal_charged_ns;++unsignedlongesz;/* Effective size quota in bytes */++/* For charging the quota */unsignedlongcharged_sz;unsignedlongcharged_from;structdamon_target*charge_target_from;
@@ -625,6 +635,29 @@ static void damon_do_apply_schemes(struct damon_ctx *c,}}+/* Shouldn't be called if quota->ms and quota->sz are zero */+staticvoiddamos_set_effective_quota(structdamos_quota*quota)+{+unsignedlongthroughput;+unsignedlongesz;++if(!quota->ms){+quota->esz=quota->sz;+return;+}++if(quota->total_charged_ns)+throughput=quota->total_charged_sz*1000000/+quota->total_charged_ns;+else+throughput=PAGE_SIZE*1024;+esz=throughput*quota->ms;++if(quota->sz&"a->sz<esz)+esz=quota->sz;+quota->esz=esz;+}+staticvoidkdamond_apply_schemes(structdamon_ctx*c){structdamon_target*t;