提交 a055ee2c 编写于 作者: Y Yihao Wu

alinux: sched: Add cgroup-level blocked time histograms

to #28739709

This patch measures time that tasks in cpuacct cgroup blocks. There
are two types: blocked due to IO, and others like locks. And they
are exported in"cpuacct.ioblock_latency" and "cpuacct.block_latency"
respectively.

According to histogram, we know the detailed distribution of the
duration. And according to total(ms), we know the percentage of time
tasks spent off rq, waiting for resources:

(△ioblock_latency.total(ms) + △block_latency.total(ms)) / △wall_time

The interface output format is identical to cpuacct.wait_latency.
Signed-off-by: NYihao Wu <wuyihao@linux.alibaba.com>
Acked-by: NXunlei Pang <xlpang@linux.alibaba.com>
Reviewed-by: NShanpei Chen <shanpeic@linux.alibaba.com>
Acked-by: NMichael Wang <yun.wang@linux.alibaba.com>
上级 76d98609
...@@ -35,6 +35,8 @@ struct cpuacct_alistats { ...@@ -35,6 +35,8 @@ struct cpuacct_alistats {
enum sched_lat_stat_item { enum sched_lat_stat_item {
SCHED_LAT_WAIT, SCHED_LAT_WAIT,
SCHED_LAT_BLOCK,
SCHED_LAT_IOBLOCK,
SCHED_LAT_NR_STAT SCHED_LAT_NR_STAT
}; };
...@@ -229,6 +231,30 @@ void task_ca_increase_nr_migrations(struct task_struct *tsk) ...@@ -229,6 +231,30 @@ void task_ca_increase_nr_migrations(struct task_struct *tsk)
rcu_read_unlock(); rcu_read_unlock();
} }
void task_ca_update_block(struct task_struct *tsk, u64 runtime)
{
int idx;
enum sched_lat_stat_item s;
struct cpuacct *ca;
unsigned int msecs;
if (static_branch_likely(&cpuacct_no_sched_lat))
return;
rcu_read_lock();
ca = task_ca(tsk);
if (tsk->in_iowait)
s = SCHED_LAT_IOBLOCK;
else
s = SCHED_LAT_BLOCK;
msecs = runtime >> 20; /* Proximately to speed up */
idx = get_sched_lat_count_idx(msecs);
this_cpu_inc(ca->lat_stat_cpu->item[s][idx]);
this_cpu_add(ca->lat_stat_cpu->item[s][SCHED_LAT_TOTAL], runtime);
rcu_read_unlock();
}
void cpuacct_update_latency(struct task_struct *tsk, u64 delta) void cpuacct_update_latency(struct task_struct *tsk, u64 delta)
{ {
enum sched_lat_count_t idx; enum sched_lat_count_t idx;
...@@ -780,9 +806,13 @@ static void smp_write_##name(void *info) \ ...@@ -780,9 +806,13 @@ static void smp_write_##name(void *info) \
} \ } \
SCHED_LAT_STAT_SMP_WRITE(sched_wait_latency, SCHED_LAT_WAIT); SCHED_LAT_STAT_SMP_WRITE(sched_wait_latency, SCHED_LAT_WAIT);
SCHED_LAT_STAT_SMP_WRITE(sched_block_latency, SCHED_LAT_BLOCK);
SCHED_LAT_STAT_SMP_WRITE(sched_ioblock_latency, SCHED_LAT_IOBLOCK);
smp_call_func_t smp_sched_lat_write_funcs[] = { smp_call_func_t smp_sched_lat_write_funcs[] = {
smp_write_sched_wait_latency smp_write_sched_wait_latency,
smp_write_sched_block_latency,
smp_write_sched_ioblock_latency
}; };
static int sched_lat_stat_write(struct cgroup_subsys_state *css, static int sched_lat_stat_write(struct cgroup_subsys_state *css,
...@@ -892,6 +922,18 @@ static struct cftype files[] = { ...@@ -892,6 +922,18 @@ static struct cftype files[] = {
.write_u64 = sched_lat_stat_write, .write_u64 = sched_lat_stat_write,
.seq_show = sched_lat_stat_show .seq_show = sched_lat_stat_show
}, },
{
.name = "block_latency",
.private = SCHED_LAT_BLOCK,
.write_u64 = sched_lat_stat_write,
.seq_show = sched_lat_stat_show
},
{
.name = "ioblock_latency",
.private = SCHED_LAT_IOBLOCK,
.write_u64 = sched_lat_stat_write,
.seq_show = sched_lat_stat_show
},
#endif #endif
{ } /* terminate */ { } /* terminate */
}; };
......
...@@ -945,6 +945,7 @@ update_stats_enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) ...@@ -945,6 +945,7 @@ update_stats_enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
__schedstat_add(se->statistics.sum_sleep_runtime, delta); __schedstat_add(se->statistics.sum_sleep_runtime, delta);
if (tsk) { if (tsk) {
task_ca_update_block(tsk, delta);
if (tsk->in_iowait) { if (tsk->in_iowait) {
__schedstat_add(se->statistics.iowait_sum, delta); __schedstat_add(se->statistics.iowait_sum, delta);
__schedstat_inc(se->statistics.iowait_count); __schedstat_inc(se->statistics.iowait_count);
......
...@@ -2283,10 +2283,13 @@ extern u64 get_idle_time(int cpu); ...@@ -2283,10 +2283,13 @@ extern u64 get_idle_time(int cpu);
extern u64 get_iowait_time(int cpu); extern u64 get_iowait_time(int cpu);
extern void task_ca_increase_nr_migrations(struct task_struct *tsk); extern void task_ca_increase_nr_migrations(struct task_struct *tsk);
void cpuacct_update_latency(struct task_struct *tsk, u64 delta); void cpuacct_update_latency(struct task_struct *tsk, u64 delta);
void task_ca_update_block(struct task_struct *tsk, u64 runtime);
#else #else
static inline void task_ca_increase_nr_migrations(struct task_struct *tsk) { } static inline void task_ca_increase_nr_migrations(struct task_struct *tsk) { }
static inline void cpuacct_update_latency(struct task_struct *tsk, static inline void cpuacct_update_latency(struct task_struct *tsk,
u64 delta) { } u64 delta) { }
static inline void task_ca_update_block(struct task_struct *tsk,
u64 runtime) { }
#endif #endif
#ifdef CONFIG_PSI #ifdef CONFIG_PSI
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册