[Devel] [PATCH RHEL9 COMMIT] ms/mm/ksm: add sysfs knobs for advisor
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Aug 27 20:29:10 MSK 2024
The commit is pushed to "branch-rh9-5.14.0-427.31.1.vz9.70.x-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh9-5.14.0-427.31.1.vz9.68.1
------>
commit 8d7b99978f1c711785b2abc095a5999b12c02251
Author: Stefan Roesch <shr at devkernel.io>
Date: Wed Aug 21 14:45:44 2024 +0800
ms/mm/ksm: add sysfs knobs for advisor
This adds four new knobs for the KSM advisor to influence its behaviour.
The knobs are:
- advisor_mode:
none: no advisor (default)
scan-time: scan time advisor
- advisor_max_cpu: 70 (default, cpu usage percent)
- advisor_min_pages_to_scan: 500 (default)
- advisor_max_pages_to_scan: 30000 (default)
- advisor_target_scan_time: 200 (default in seconds)
The new values will take effect on the next scan round.
Link: https://lkml.kernel.org/r/20231218231054.1625219-3-shr@devkernel.io
Signed-off-by: Stefan Roesch <shr at devkernel.io>
Acked-by: David Hildenbrand <david at redhat.com>
Cc: Johannes Weiner <hannes at cmpxchg.org>
Cc: Rik van Riel <riel at surriel.com>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
https://virtuozzo.atlassian.net/browse/PSBM-157809
(cherry picked from commit 66790e9a735b5c42349c48881e496b6946a55c05)
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
======
Patchset description:
ksm: port smart scanning and advisor to improve performance
1) "Smart" scanning allows ksm to skip pages which didn't manage to be
deduplicated after several iterations, it skips those pages for maximum
8 iterations and then retries again. To enable:
echo 1 > /sys/kernel/mm/ksm/smart_scan
2) Ksm Advisor allows ksm to autoscale pages_to_scan based on previous
scans data to perform full memory scan in advisor_target_scan_time
(200s by default). It will increase scanning rate if new processes with
more pages to deduplicate start and will decrease performance impact
in more stable situations. To enable:
echo "scan-time" /sys/kernel/mm/ksm/advisor_mode
note: Don't forget to enable ksm, when using above, with:
echo 1 > /sys/kernel/mm/ksm/run
note: It shows greater performance on sysbench and webbench perf tests
in vconsolidate on csus > 40.
https://virtuozzo.atlassian.net/browse/PSBM-157809
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Stefan Roesch (4):
mm/ksm: add "smart" page scanning mode
mm/ksm: add pages_skipped metric
mm/ksm: add ksm advisor
mm/ksm: add sysfs knobs for advisor
Feature: ksm: smart scanning and advisor
---
mm/ksm.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 148 insertions(+)
diff --git a/mm/ksm.c b/mm/ksm.c
index c4a95afb3b40..edc046c62f40 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -328,6 +328,25 @@ enum ksm_advisor_type {
};
static enum ksm_advisor_type ksm_advisor;
+#ifdef CONFIG_SYSFS
+/*
+ * Only called through the sysfs control interface:
+ */
+
+/* At least scan this many pages per batch. */
+static unsigned long ksm_advisor_min_pages_to_scan = 500;
+
+static void set_advisor_defaults(void)
+{
+ if (ksm_advisor == KSM_ADVISOR_NONE) {
+ ksm_thread_pages_to_scan = DEFAULT_PAGES_TO_SCAN;
+ } else if (ksm_advisor == KSM_ADVISOR_SCAN_TIME) {
+ advisor_ctx = (const struct advisor_ctx){ 0 };
+ ksm_thread_pages_to_scan = ksm_advisor_min_pages_to_scan;
+ }
+}
+#endif /* CONFIG_SYSFS */
+
static inline void advisor_start_scan(void)
{
if (ksm_advisor == KSM_ADVISOR_SCAN_TIME)
@@ -3414,6 +3433,130 @@ static ssize_t smart_scan_store(struct kobject *kobj,
}
KSM_ATTR(smart_scan);
+static ssize_t advisor_mode_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ const char *output;
+
+ if (ksm_advisor == KSM_ADVISOR_NONE)
+ output = "[none] scan-time";
+ else if (ksm_advisor == KSM_ADVISOR_SCAN_TIME)
+ output = "none [scan-time]";
+
+ return sysfs_emit(buf, "%s\n", output);
+}
+
+static ssize_t advisor_mode_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf,
+ size_t count)
+{
+ enum ksm_advisor_type curr_advisor = ksm_advisor;
+
+ if (sysfs_streq("scan-time", buf))
+ ksm_advisor = KSM_ADVISOR_SCAN_TIME;
+ else if (sysfs_streq("none", buf))
+ ksm_advisor = KSM_ADVISOR_NONE;
+ else
+ return -EINVAL;
+
+ /* Set advisor default values */
+ if (curr_advisor != ksm_advisor)
+ set_advisor_defaults();
+
+ return count;
+}
+KSM_ATTR(advisor_mode);
+
+static ssize_t advisor_max_cpu_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%u\n", ksm_advisor_max_cpu);
+}
+
+static ssize_t advisor_max_cpu_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long value;
+
+ err = kstrtoul(buf, 10, &value);
+ if (err)
+ return -EINVAL;
+
+ ksm_advisor_max_cpu = value;
+ return count;
+}
+KSM_ATTR(advisor_max_cpu);
+
+static ssize_t advisor_min_pages_to_scan_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%lu\n", ksm_advisor_min_pages_to_scan);
+}
+
+static ssize_t advisor_min_pages_to_scan_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long value;
+
+ err = kstrtoul(buf, 10, &value);
+ if (err)
+ return -EINVAL;
+
+ ksm_advisor_min_pages_to_scan = value;
+ return count;
+}
+KSM_ATTR(advisor_min_pages_to_scan);
+
+static ssize_t advisor_max_pages_to_scan_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%lu\n", ksm_advisor_max_pages_to_scan);
+}
+
+static ssize_t advisor_max_pages_to_scan_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long value;
+
+ err = kstrtoul(buf, 10, &value);
+ if (err)
+ return -EINVAL;
+
+ ksm_advisor_max_pages_to_scan = value;
+ return count;
+}
+KSM_ATTR(advisor_max_pages_to_scan);
+
+static ssize_t advisor_target_scan_time_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%lu\n", ksm_advisor_target_scan_time);
+}
+
+static ssize_t advisor_target_scan_time_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ unsigned long value;
+
+ err = kstrtoul(buf, 10, &value);
+ if (err)
+ return -EINVAL;
+ if (value < 1)
+ return -EINVAL;
+
+ ksm_advisor_target_scan_time = value;
+ return count;
+}
+KSM_ATTR(advisor_target_scan_time);
+
static struct attribute *ksm_attrs[] = {
&sleep_millisecs_attr.attr,
&pages_to_scan_attr.attr,
@@ -3433,6 +3576,11 @@ static struct attribute *ksm_attrs[] = {
&stable_node_chains_prune_millisecs_attr.attr,
&use_zero_pages_attr.attr,
&smart_scan_attr.attr,
+ &advisor_mode_attr.attr,
+ &advisor_max_cpu_attr.attr,
+ &advisor_min_pages_to_scan_attr.attr,
+ &advisor_max_pages_to_scan_attr.attr,
+ &advisor_target_scan_time_attr.attr,
NULL,
};
More information about the Devel
mailing list