[Devel] [PATCH rh7 v3 4/4] /proc/<pid>/vz_latency: Show maximal allocation latency in the last second.

Denis V. Lunev den at virtuozzo.com
Thu Aug 30 14:13:31 MSK 2018


On 08/23/2018 07:12 PM, Andrey Ryabinin wrote:
> Add to '/proc/<pid>/vz_latency' column with maximal latency task have seen
> in the last 2 minutes.
>
> E.g.:
>
> cat /proc/1/vz_latency
> Type                    Total_lat                Calls           Max (2min)
> allocatomic:                    0                  294                    0
> alloc:                    3000000                43394                    0
> allocmp:                        0                 1018                    0
>
> AFAICS this changes output format but shouldn't break our the only user of
> this interface - pstorage. Accordind to the pstorage code it reads this
> file line by line, reads 'Total_lat' and 'Calls' fields and skips to the next
> line. Thus adding new field shouldn't break it.
>
> https://jira.sw.ru/browse/PSBM-87797
> Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
> Cc: Pavel Borzenkov <Pavel.Borzenkov at acronis.com>
> ---
>
> Chnages since v2:
>  - fix header text.
>  - Change the way max value calculated. Instead of reset the val once per 2 min
>     record 2 maxes per minute in last 2 minutes and show the max of these maxes. 
>
> Changes since v1:
>  - change period from 1sec to 2min
>
>  fs/proc/base.c          | 28 ++++++++++++++++++++--------
>  include/linux/kstat.h   |  3 ++-
>  include/linux/vzstat.h  | 15 +++++++++++++++
>  kernel/exit.c           | 13 +++++++++++++
>  kernel/ve/vzstat_core.c |  6 +++---
>  mm/page_alloc.c         | 35 +++++++++++++++++++++++++++++++++++
>  6 files changed, 88 insertions(+), 12 deletions(-)
>
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index 64bbbc387afc..222b4cfeed8e 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -80,6 +80,7 @@
>  #include <linux/audit.h>
>  #include <linux/poll.h>
>  #include <linux/nsproxy.h>
> +#include <linux/vzstat.h>
>  #include <linux/oom.h>
>  #include <linux/elf.h>
>  #include <linux/pid_namespace.h>
> @@ -580,8 +581,8 @@ static void lastlat_seq_show(struct seq_file *m,
>  		const char *name,
>  		struct kstat_lat_snap_struct *snap)
>  {
> -	seq_printf(m, "%-12s %20Lu %20lu\n", name,
> -			snap->totlat, snap->count);
> +	seq_printf(m, "%-12s %20Lu %20lu %20Lu\n", name,
> +			snap->totlat, snap->count, get_max_lat(snap));
>  }
>  static const char *alloc_descr[] = {
>  	"allocatomic:",
> @@ -599,8 +600,8 @@ static int proc_tid_vz_lat(struct seq_file *m, struct pid_namespace *ns,
>  {
>  	int i;
>  
> -	seq_printf(m, "%-12s %20s %20s\n",
> -			"Type", "Total_lat", "Calls");
> +	seq_printf(m, "%-12s %20s %20s %20s\n",
> +			"Type", "Total_lat", "Calls", "Max (2min)");
>  
>  	for (i = 0; i < ARRAY_SIZE(alloc_types); i++)
>  		lastlat_seq_show(m, alloc_descr[i],
> @@ -615,33 +616,44 @@ static int proc_tgid_vz_lat(struct seq_file *m, struct pid_namespace *ns,
>  	unsigned long flags;
>  	u64 lat[ARRAY_SIZE(alloc_types)];
>  	u64 count[ARRAY_SIZE(alloc_types)];
> +	u64 maxlats[ARRAY_SIZE(alloc_types)];
>  
>  	for (i = 0; i < ARRAY_SIZE(alloc_types); i++) {
>  		lat[i] = task->alloc_lat[alloc_types[i]].totlat;
>  		count[i] = task->alloc_lat[alloc_types[i]].count;
> +		maxlats[i] = get_max_lat(&task->alloc_lat[alloc_types[i]]);
>  	}
>  
>  	if (lock_task_sighand(task, &flags)) {
>  		struct task_struct *t = task;
> +		u64 maxlat;
> +
>  		while_each_thread(task, t) {
>  			for (i = 0; i < ARRAY_SIZE(alloc_types); i++) {
>  				lat[i] += t->alloc_lat[alloc_types[i]].totlat;
>  				count[i] += t->alloc_lat[alloc_types[i]].count;
> +				maxlat = get_max_lat(&t->alloc_lat[alloc_types[i]]);
> +				if (maxlats[i] < maxlat)
> +					maxlats[i] = maxlat;
>  			}
>  		}
>  		for (i = 0; i < ARRAY_SIZE(alloc_types); i++) {
>  			lat[i] += t->signal->alloc_lat[alloc_types[i]].totlat;
>  			count[i] += t->signal->alloc_lat[alloc_types[i]].count;
> +			maxlat = get_max_lat(&t->signal->alloc_lat[alloc_types[i]]);
> +			if (maxlats[i] < maxlat)
> +				maxlats[i] = maxlat;
> +
>  		}
>  		unlock_task_sighand(task, &flags);
>  	}
>  
> -	seq_printf(m, "%-12s %20s %20s\n",
> -			"Type", "Total_lat", "Calls");
> +	seq_printf(m, "%-12s %20s %20s %20s\n",
> +			"Type", "Total_lat", "Calls", "Max (2min)");
>  
>  	for (i = 0; i < ARRAY_SIZE(alloc_types); i++)
> -		seq_printf(m, "%-12s %20Lu %20Lu\n", alloc_descr[i],
> -			lat[i], count[i]);
> +		seq_printf(m, "%-12s %20Lu %20Lu %20Lu\n", alloc_descr[i],
> +			lat[i], count[i], maxlats[i]);
>  
>  	return 0;
>  }
> diff --git a/include/linux/kstat.h b/include/linux/kstat.h
> index b268752f2e15..1e42c0317e6e 100644
> --- a/include/linux/kstat.h
> +++ b/include/linux/kstat.h
> @@ -30,8 +30,9 @@ struct kstat_perf_pcpu_struct {
>  };
>  
>  struct kstat_lat_snap_struct {
> -	u64 maxlat, totlat;
> +	u64 maxlat[2], totlat;
>  	unsigned long count;
> +	unsigned long time[2];
>  };
>  
>  struct kstat_lat_pcpu_snap_struct {
> diff --git a/include/linux/vzstat.h b/include/linux/vzstat.h
> index f1475b2b763a..bfd3b461cb4c 100644
> --- a/include/linux/vzstat.h
> +++ b/include/linux/vzstat.h
> @@ -9,6 +9,7 @@
>  #ifndef __VZSTAT_H__
>  #define __VZSTAT_H__
>  
> +#include <linux/jiffies.h>
>  #include <linux/mmzone.h>
>  #include <linux/kstat.h>
>  
> @@ -64,6 +65,20 @@ extern void KSTAT_PERF_ADD(struct kstat_perf_pcpu_struct *ptr, u64 real_time,
>  	sleep_time = current->se.statistics->sum_sleep_runtime - sleep_time; \
>  	KSTAT_PERF_ADD(&kstat_glob.name, start, start - sleep_time);
>  
> +#define KSTAT_ALLOC_MAX_LAT_PERIOD (120*HZ)
> +
> +static inline u64 get_max_lat(struct kstat_lat_snap_struct *snap)
> +{
> +	int i;
> +	u64 max = 0;
> +
> +	for (i = 0; i < 2; i++) {
> +		if (time_before(jiffies, snap->time[i] + KSTAT_ALLOC_MAX_LAT_PERIOD))
> +			max = max > snap->maxlat[i] ? max : snap->maxlat[i];
> +	}
> +	return max;
> +}
> +
>  extern void KSTAT_LAT_PCPU_ADD(struct kstat_lat_pcpu_struct *p, u64 dur);
>  extern void KSTAT_LAT_PCPU_UPDATE(struct kstat_lat_pcpu_struct *p);
>  
> diff --git a/kernel/exit.c b/kernel/exit.c
> index bf68b87a4d60..c926cca30df3 100644
> --- a/kernel/exit.c
> +++ b/kernel/exit.c
> @@ -735,6 +735,9 @@ static void check_stack_usage(void)
>  static inline void check_stack_usage(void) {}
>  #endif
>  
> +void update_maxlat(struct kstat_lat_snap_struct *alloc_lat,
> +				u64 lat, unsigned long time);
> +
>  void kstat_add_dying(struct task_struct *tsk)
>  {
>  #ifdef CONFIG_VE
> @@ -742,8 +745,18 @@ void kstat_add_dying(struct task_struct *tsk)
>  
>  	spin_lock_irq(&tsk->sighand->siglock);
>  	for (i = 0; i < KSTAT_ALLOCSTAT_NR; i++) {
> +		int j;
> +
>  		tsk->signal->alloc_lat[i].totlat += tsk->alloc_lat[i].totlat;
>  		tsk->signal->alloc_lat[i].count += tsk->alloc_lat[i].count;
> +		for (j = 0; j < 2; j++) {
> +			if (time_after(tsk->signal->alloc_lat[i].time[j],
> +					tsk->alloc_lat[i].time[0])) {
> +				update_maxlat(&tsk->alloc_lat[i],
> +					tsk->signal->alloc_lat[i].maxlat[j],
> +					tsk->signal->alloc_lat[i].time[j]);
> +			}
> +		}
>  	}
>  	spin_unlock_irq(&tsk->sighand->siglock);
>  #endif
> diff --git a/kernel/ve/vzstat_core.c b/kernel/ve/vzstat_core.c
> index 2501422d146b..4370c4b5c504 100644
> --- a/kernel/ve/vzstat_core.c
> +++ b/kernel/ve/vzstat_core.c
> @@ -87,11 +87,11 @@ void KSTAT_LAT_PCPU_UPDATE(struct kstat_lat_pcpu_struct *p)
>  
>  		p->last.count += snap.count;
>  		p->last.totlat += snap.totlat;
> -		if (p->last.maxlat < snap.maxlat)
> -			p->last.maxlat = snap.maxlat;
> +		if (p->last.maxlat[0] < snap.maxlat)
> +			p->last.maxlat[0] = snap.maxlat;
>  	}
>  
> -	m = (p->last.maxlat > p->max_snap ? p->last.maxlat : p->max_snap);
> +	m = (p->last.maxlat[0] > p->max_snap ? p->last.maxlat[0] : p->max_snap);
>  	CALC_LOAD(p->avg[0], EXP_1, m);
>  	CALC_LOAD(p->avg[1], EXP_5, m);
>  	CALC_LOAD(p->avg[2], EXP_15, m);
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 9d8c9e4eb970..3d22c4301dc9 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -3214,6 +3214,40 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
>  	return page;
>  }
>  
> +void update_maxlat(struct kstat_lat_snap_struct *alloc_lat,
> +				u64 lat, unsigned long time)
> +{
> +	if (time_before(time, alloc_lat->time[0] +
> +				KSTAT_ALLOC_MAX_LAT_PERIOD/2)) {
> +		if (alloc_lat->maxlat[0] < lat) {
> +			alloc_lat->maxlat[0] = lat;
> +			alloc_lat->time[0] = time;
> +		}
> +	} else if (time_before(time, alloc_lat->time[0] +
> +				KSTAT_ALLOC_MAX_LAT_PERIOD)) {
> +		if (alloc_lat->maxlat[1] < lat) {
> +			alloc_lat->maxlat[1] = lat;
> +			alloc_lat->time[1] = time;
> +		}
> +	} else if (time_before(time, alloc_lat->time[0] +
> +				KSTAT_ALLOC_MAX_LAT_PERIOD*3/2)) {
> +		if (alloc_lat->maxlat[1] < lat) {
> +			alloc_lat->maxlat[0] = lat;
> +			alloc_lat->time[0] = time;
> +		} else {
> +			alloc_lat->maxlat[0] = alloc_lat->maxlat[1];
> +			alloc_lat->time[0] = alloc_lat->time[1];
> +		}
> +		alloc_lat->maxlat[1] = 0;
> +		alloc_lat->time[1] = 0;
> +	} else {
> +		alloc_lat->maxlat[0] = lat;
> +		alloc_lat->time[0] = time;
> +		alloc_lat->maxlat[1] = 0;
> +		alloc_lat->time[1] = 0;
> +	}
> +}
> +
>  static void __alloc_collect_stats(gfp_t gfp_mask, unsigned int order,
>  		struct page *page, u64 time)
>  {
> @@ -3241,6 +3275,7 @@ static void __alloc_collect_stats(gfp_t gfp_mask, unsigned int order,
>  	if (in_task()) {
>  		current->alloc_lat[ind].totlat += time;
>  		current->alloc_lat[ind].count++;
> +		update_maxlat(&current->alloc_lat[ind], time, jiffies);
>  	}
>  
>  	if (!page)
Reviewed-by: Denis V. Lunev <den at openvz.org>


More information about the Devel mailing list