From: Tang Yizhou tangyizhou@huawei.com
ascend inclusion category: perf bugzilla: https://gitee.com/openeuler/kernel/issues/I4EUVI CVE: NA
-------------------------------------------------
We did an compaction experiment on Hi1951. First creating external fragmentation, then echo 1 > /proc/sys/vm/compact_memory.
Fragmentation size | 0G | 2G | 4G | 8G Compaction time(s) | 0.07 | 0.85 | 1.7 | 3.4
Obviously, sysctl_compaction_handler has a big performance impact.
We optimize share pool compact procedure as follows: 1. At most one compact daemon is allowed. 2. Creating a compact daemon is only allowed when the last one is finished at least *sysctl_sp_compact_interval* seconds ago.
Signed-off-by: Tang Yizhou tangyizhou@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/share_pool.h | 4 ++++ kernel/sysctl.c | 18 ++++++++++++++++++ mm/share_pool.c | 24 +++++++++++++++++++++--- 3 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h index 9d81fc7a94c7c..164efeb81889d 100644 --- a/include/linux/share_pool.h +++ b/include/linux/share_pool.h @@ -40,6 +40,10 @@ extern int enable_ascend_share_pool;
extern int sysctl_share_pool_map_lock_enable;
+extern int sysctl_sp_compact_enable; +extern unsigned long sysctl_sp_compact_interval; +extern unsigned long sysctl_sp_compact_interval_max; + #ifdef CONFIG_HAVE_ARCH_HUGE_VMALLOC extern bool vmap_allow_huge; #endif diff --git a/kernel/sysctl.c b/kernel/sysctl.c index cd2d114f3391c..c5d4395efd430 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1789,6 +1789,24 @@ static struct ctl_table vm_table[] = { .extra1 = &zero, .extra2 = &one, }, + { + .procname = "sharepool_compact_enable", + .data = &sysctl_sp_compact_enable, + .maxlen = sizeof(sysctl_sp_compact_enable), + .mode = 0600, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { + .procname = "sharepool_compact_interval", + .data = &sysctl_sp_compact_interval, + .maxlen = sizeof(sysctl_sp_compact_interval), + .mode = 0600, + .proc_handler = proc_doulongvec_minmax, + .extra1 = &zero_ul, + .extra2 = &sysctl_sp_compact_interval_max, + }, #endif { } }; diff --git a/mm/share_pool.c b/mm/share_pool.c index 4c9105722c35e..ad842151f1c71 100644 --- a/mm/share_pool.c +++ b/mm/share_pool.c @@ -1127,26 +1127,44 @@ void sp_area_drop(struct vm_area_struct *vma) spin_unlock(&sp_area_lock); }
-static unsigned long last_jiffies; +int sysctl_sp_compact_enable; +unsigned long sysctl_sp_compact_interval = 30UL; +unsigned long sysctl_sp_compact_interval_max = 1000UL; +static unsigned long compact_last_jiffies; +static unsigned long compact_daemon_status; +#define COMPACT_START 1 +#define COMPACT_STOP 0 + static void sp_compact_nodes(struct work_struct *work) { sysctl_compaction_handler(NULL, 1, NULL, NULL, NULL);
kfree(work); + + compact_last_jiffies = jiffies; + cmpxchg(&compact_daemon_status, COMPACT_START, COMPACT_STOP); }
static void sp_add_work_compact(void) { struct work_struct *compact_work;
- if (!time_after(jiffies, last_jiffies + 10 * HZ)) + if (!sysctl_sp_compact_enable) + return; + + /* experimental compaction time: 4GB->1.7s, 8GB->3.4s */ + if (!time_after(jiffies, + compact_last_jiffies + sysctl_sp_compact_interval * HZ)) + return; + + if (cmpxchg(&compact_daemon_status, COMPACT_STOP, COMPACT_START) == + COMPACT_START) return;
compact_work = kzalloc(sizeof(*compact_work), GFP_KERNEL); if (!compact_work) return;
- last_jiffies = jiffies; INIT_WORK(compact_work, sp_compact_nodes); schedule_work(compact_work); }