From 1435e60d749063435a544942021cbb1c54a1e7a3 Mon Sep 17 00:00:00 2001 From: Yi Tao Date: Fri, 8 Jan 2021 11:25:24 +0800 Subject: [PATCH 2534/2944] alinux: cpuacct: use cache when creating cpuacct to #31531504 Allocating memory for some percpu members of cpuacct when creating new cpuacct accounts for the largest percentage of time. So we reuse memory allocated for percpu members. When freeing cpuacct, record address of memory used by percpu members rather freeing them. At the stage of creating cpuacct, use struct cpuacct from cache directly. performance test: env: Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz method: get system time at the beginning and end of function cpuacct_css_alloc() then output time. create cgroup under cpuacct subsystem in batch and calculate average time. avg time of cpuacct_css_alloc() without cache: 61276.1ns with cache: 9184.14ns Signed-off-by: Yi Tao Suggested-by: Shanpei Chen Acked-by: Michael Wang --- kernel/sched/cpuacct.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c index d079a4f..ca37c53 100644 --- a/kernel/sched/cpuacct.c +++ b/kernel/sched/cpuacct.c @@ -295,6 +295,36 @@ void cpuacct_update_latency(struct sched_entity *se, u64 delta) } #endif +static void cpuacct_clean_up(void **ptr) +{ + struct cpuacct *ca = *ptr; + struct cpuacct_usage __percpu *cpuusage = ca->cpuusage; + struct kernel_cpustat __percpu *cpustat = ca->cpustat; +#ifdef CONFIG_SCHED_SLI + struct cpuacct_alistats __percpu *alistats = ca->alistats; + struct sched_cgroup_lat_stat_cpu __percpu *lat_stat_cpu = ca->lat_stat_cpu; +#endif + int i; + + for_each_possible_cpu(i) { + memset(per_cpu_ptr(cpuusage, i), 0, sizeof(*cpuusage)); + memset(per_cpu_ptr(cpustat, i), 0, sizeof(*cpustat)); +#ifdef CONFIG_SCHED_SLI + memset(per_cpu_ptr(alistats, i), 0, sizeof(*alistats)); + memset(per_cpu_ptr(lat_stat_cpu, i), 0, sizeof(*lat_stat_cpu)); +#endif + } + + memset(ca, 0, sizeof(*ca)); + + ca->cpuusage = cpuusage; + ca->cpustat = cpustat; +#ifdef CONFIG_SCHED_SLI + ca->alistats = alistats; + ca->lat_stat_cpu = lat_stat_cpu; +#endif +} + static void cpuacct_free(void **ptr) { struct cpuacct *ca = *ptr; @@ -308,6 +338,9 @@ static void cpuacct_free(void **ptr) kfree(ca); } +CACHE_HEADER(cpuacct_cache_header, DEFAULT_CACHE_SIZE, + cpuacct_clean_up, cpuacct_free); + static void cpuacct_init(struct cpuacct *ca) { int i; @@ -327,6 +360,11 @@ static void cpuacct_init(struct cpuacct *ca) if (!parent_css) return &root_cpuacct.css; + if (get_from_cache(&cpuacct_cache_header, (void **)&ca, 1)) { + cpuacct_init(ca); + return &ca->css; + } + ca = kzalloc(sizeof(*ca), GFP_KERNEL); if (!ca) goto out; @@ -372,6 +410,9 @@ static void cpuacct_css_free(struct cgroup_subsys_state *css) { struct cpuacct *ca = css_ca(css); + if (put_to_cache(&cpuacct_cache_header, (void **)&ca, 1)) + return; + cpuacct_free((void **)&ca); } -- 1.8.3.1