From bcaf8afd6270e99640ca6f6612184c1a5148c219 Mon Sep 17 00:00:00 2001 From: Yihao Wu Date: Wed, 13 May 2020 14:32:51 +0800 Subject: [PATCH 1461/2944] alinux: sched: Add switch for scheduler_tick load tracking to #28739709 Assume workloads are composed of massive short tasks. Then periodical load tracking is unnecessary. Because load tracking should be already guaranteed by frequent sleep and wake-up. If these massive short tasks run in their individual cgroups, the load tracking becomes extremely heavy. This patch adds a switch to bypass scheduler_tick load tracking, in order to reduce scheduler overhead, without sacrificing much balance in this scenario. Performance Tests: 1) 1100+ tasks in their individual cgroups, on a 96-HT Skylake machine sched overhead(each HT): 0.74% -> 0.48% (This test's baseline is from the previous patch) 2) sysbench-threads with 96 threads, running for 5min latency_ms 95th: 63.07 -> 54.01 Besides these, no regression is found on our test platform. Signed-off-by: Yihao Wu Acked-by: Michael Wang --- include/linux/sched/sysctl.h | 5 +++++ kernel/sched/fair.c | 42 +++++++++++++++++++++++++++++++++++++----- kernel/sysctl.c | 9 +++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index efa5111..43205f0 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -87,5 +87,10 @@ extern int sysctl_blocked_averages(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +extern int sysctl_tick_update_load(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos); + +extern struct static_key_true sched_tick_update_load; extern struct static_key_true sched_blocked_averages; #endif /* _LINUX_SCHED_SYSCTL_H */ diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 853a979..f98a840 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4233,6 +4233,36 @@ static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev) cfs_rq->curr = NULL; } +DEFINE_STATIC_KEY_TRUE(sched_tick_update_load); + +static void set_tick_update_load(bool enabled) +{ + if (enabled) + static_branch_enable(&sched_tick_update_load); + else + static_branch_disable(&sched_tick_update_load); +} + +int sysctl_tick_update_load(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + struct ctl_table t; + int err; + int state = static_branch_likely(&sched_tick_update_load); + + if (write && !capable(CAP_SYS_ADMIN)) + return -EPERM; + + t = *table; + t.data = &state; + err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos); + if (err < 0) + return err; + if (write) + set_tick_update_load(state); + return err; +} + static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued) { @@ -4241,11 +4271,13 @@ static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev) */ update_curr(cfs_rq); - /* - * Ensure that runnable average is periodically updated. - */ - update_load_avg(cfs_rq, curr, UPDATE_TG); - update_cfs_group(curr); + if (static_branch_likely(&sched_tick_update_load)) { + /* + * Ensure that runnable average is periodically updated. + */ + update_load_avg(cfs_rq, curr, UPDATE_TG); + update_cfs_group(curr); + } #ifdef CONFIG_SCHED_HRTICK /* diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 2a2a493..73219fc5 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -355,6 +355,15 @@ static int sysrq_sysctl_handler(struct ctl_table *table, int write, }, #ifdef CONFIG_SMP { + .procname = "sched_tick_update_load", + .data = NULL, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = sysctl_tick_update_load, + .extra1 = &zero, + .extra2 = &one, + }, + { .procname = "sched_blocked_averages", .data = NULL, .maxlen = sizeof(unsigned int), -- 1.8.3.1