2021-12-03 14:38:33

by Yong Wang

[permalink] [raw]
Subject: [PATCH linux-next] delayacct: track delays from memory compact

From: wangyong <[email protected]>

Delay accounting does not track the delay of memory compact.
When there is not enough free memory, tasks can spend
a amount of their time waiting for memory compact.

To get the impact of tasks in direct memory compact, measure
the delay when allocating memory through memory compact.

Update tools/accounting/getdelays.c:
/ # ./getdelays_next -di -p 304
print delayacct stats ON
printing IO accounting
PID 304

CPU count real total virtual total delay total delay average
277 780000000 849039485 18877296 0.068ms
IO count delay total delay average
0 0 0ms
SWAP count delay total delay average
0 0 0ms
RECLAIM count delay total delay average
5 11088812685 2217ms
THRASHING count delay total delay average
0 0 0ms
COMPACT count delay total delay average
3 72758 0ms
watch: read=0, write=0, cancelled_write=0

Reported-by: Zeal Robot <[email protected]>
Signed-off-by: wangyong <[email protected]>
Reviewed-by: Yang Yang <[email protected]>
---
include/linux/delayacct.h | 29 +++++++++++++++++++++++++++++
include/uapi/linux/taskstats.h | 6 +++++-
kernel/delayacct.c | 15 +++++++++++++++
mm/page_alloc.c | 3 +++
tools/accounting/getdelays.c | 8 +++++++-
5 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h
index 435c365..547cba9 100644
--- a/include/linux/delayacct.h
+++ b/include/linux/delayacct.h
@@ -42,8 +42,13 @@ struct task_delay_info {
u64 thrashing_start;
u64 thrashing_delay; /* wait for thrashing page */

+ u64 compact_start;
+ u64 compact_delay; /* wait for memory compact */
+
+ u64 freepages_start;
u32 freepages_count; /* total count of memory reclaim */
u32 thrashing_count; /* total count of thrash waits */
+ u32 compact_count; /* total count of memory compact */
};
#endif

@@ -72,6 +77,8 @@ extern void __delayacct_thrashing_start(void);
extern void __delayacct_thrashing_end(void);
extern void __delayacct_swapin_start(void);
extern void __delayacct_swapin_end(void);
+extern void __delayacct_compact_start(void);
+extern void __delayacct_compact_end(void);

static inline void delayacct_tsk_init(struct task_struct *tsk)
{
@@ -170,6 +177,24 @@ static inline void delayacct_swapin_end(void)
__delayacct_swapin_end();
}

+static inline void delayacct_compact_start(void)
+{
+ if (!static_branch_unlikely(&delayacct_key))
+ return;
+
+ if (current->delays)
+ __delayacct_compact_start();
+}
+
+static inline void delayacct_compact_end(void)
+{
+ if (!static_branch_unlikely(&delayacct_key))
+ return;
+
+ if (current->delays)
+ __delayacct_compact_end();
+}
+
#else
static inline void delayacct_init(void)
{}
@@ -200,6 +225,10 @@ static inline void delayacct_swapin_start(void)
{}
static inline void delayacct_swapin_end(void)
{}
+static inline void delayacct_compact_start(void)
+{}
+static inline void delayacct_compact_end(void)
+{}

#endif /* CONFIG_TASK_DELAY_ACCT */

diff --git a/include/uapi/linux/taskstats.h b/include/uapi/linux/taskstats.h
index ccbd087..12327d3 100644
--- a/include/uapi/linux/taskstats.h
+++ b/include/uapi/linux/taskstats.h
@@ -34,7 +34,7 @@
*/


-#define TASKSTATS_VERSION 10
+#define TASKSTATS_VERSION 11
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */

@@ -172,6 +172,10 @@ struct taskstats {

/* v10: 64-bit btime to avoid overflow */
__u64 ac_btime64; /* 64-bit begin time */
+
+ /* Delay waiting for memory compact */
+ __u64 compact_count;
+ __u64 compact_delay_total;
};


diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index 11f3cd8..c5e8cea 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -155,10 +155,13 @@ int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
d->freepages_delay_total = (tmp < d->freepages_delay_total) ? 0 : tmp;
tmp = d->thrashing_delay_total + tsk->delays->thrashing_delay;
d->thrashing_delay_total = (tmp < d->thrashing_delay_total) ? 0 : tmp;
+ tmp = d->compact_delay_total + tsk->delays->compact_delay;
+ d->compact_delay_total = (tmp < d->compact_delay_total) ? 0 : tmp;
d->blkio_count += tsk->delays->blkio_count;
d->swapin_count += tsk->delays->swapin_count;
d->freepages_count += tsk->delays->freepages_count;
d->thrashing_count += tsk->delays->thrashing_count;
+ d->compact_count += tsk->delays->compact_count;
raw_spin_unlock_irqrestore(&tsk->delays->lock, flags);

return 0;
@@ -214,3 +217,15 @@ void __delayacct_swapin_end(void)
&current->delays->swapin_count);
}

+void __delayacct_compact_start(void)
+{
+ current->delays->compact_start = local_clock();
+}
+
+void __delayacct_compact_end(void)
+{
+ delayacct_end(&current->delays->lock,
+ &current->delays->compact_start,
+ &current->delays->compact_delay,
+ &current->delays->compact_count);
+}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index edfd6c8..6430226 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -74,6 +74,7 @@
#include <linux/padata.h>
#include <linux/khugepaged.h>
#include <linux/buffer_head.h>
+#include <linux/delayacct.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
@@ -4363,6 +4364,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
return NULL;

psi_memstall_enter(&pflags);
+ delayacct_compact_start();
noreclaim_flag = memalloc_noreclaim_save();

*compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
@@ -4370,6 +4372,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,

memalloc_noreclaim_restore(noreclaim_flag);
psi_memstall_leave(&pflags);
+ delayacct_compact_end();

if (*compact_result == COMPACT_SKIPPED)
return NULL;
diff --git a/tools/accounting/getdelays.c b/tools/accounting/getdelays.c
index 5ef1c15..11e8673 100644
--- a/tools/accounting/getdelays.c
+++ b/tools/accounting/getdelays.c
@@ -205,6 +205,8 @@ static void print_delayacct(struct taskstats *t)
"RECLAIM %12s%15s%15s\n"
" %15llu%15llu%15llums\n"
"THRASHING%12s%15s%15s\n"
+ " %15llu%15llu%15llums\n"
+ "COMPACT %12s%15s%15s\n"
" %15llu%15llu%15llums\n",
"count", "real total", "virtual total",
"delay total", "delay average",
@@ -228,7 +230,11 @@ static void print_delayacct(struct taskstats *t)
"count", "delay total", "delay average",
(unsigned long long)t->thrashing_count,
(unsigned long long)t->thrashing_delay_total,
- average_ms(t->thrashing_delay_total, t->thrashing_count));
+ average_ms(t->thrashing_delay_total, t->thrashing_count),
+ "count", "delay total", "delay average",
+ (unsigned long long)t->compact_count,
+ (unsigned long long)t->compact_delay_total,
+ average_ms(t->compact_delay_total, t->compact_count));
}

static void task_context_switch_counts(struct taskstats *t)
--
2.7.4



2021-12-03 21:02:18

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH linux-next] delayacct: track delays from memory compact

On Fri, 3 Dec 2021 06:37:52 -0800 [email protected] wrote:

> From: wangyong <[email protected]>
>
> Delay accounting does not track the delay of memory compact.
> When there is not enough free memory, tasks can spend
> a amount of their time waiting for memory compact.
>
> To get the impact of tasks in direct memory compact, measure
> the delay when allocating memory through memory compact.
>
> ...
>
> --- a/include/linux/delayacct.h
> +++ b/include/linux/delayacct.h
> @@ -42,8 +42,13 @@ struct task_delay_info {
> u64 thrashing_start;
> u64 thrashing_delay; /* wait for thrashing page */
>
> + u64 compact_start;
> + u64 compact_delay; /* wait for memory compact */
> +
> + u64 freepages_start;

task_delay_info already has a freepages_start, so it fails to compile.

Did you send the correct version?


2021-12-04 10:21:58

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH linux-next] delayacct: track delays from memory compact

Hi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on next-20211203]

url: https://github.com/0day-ci/linux/commits/yongw-pur-gmail-com/delayacct-track-delays-from-memory-compact/20211203-224016
base: 7afeac307a9561e3a93682c1e7eb22f918aa1187
config: x86_64-randconfig-a011-20211203 (https://download.01.org/0day-ci/archive/20211204/[email protected]/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 5f1d1854eb1450d352663ee732235893c5782237)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/ccd829e34aa6aefecf6428975fa82384c6139fd1
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review yongw-pur-gmail-com/delayacct-track-delays-from-memory-compact/20211203-224016
git checkout ccd829e34aa6aefecf6428975fa82384c6139fd1
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

In file included from init/main.c:58:
>> include/linux/delayacct.h:48:6: error: duplicate member 'freepages_start'
u64 freepages_start;
^
include/linux/delayacct.h:39:6: note: previous declaration is here
u64 freepages_start;
^
init/main.c:783:20: warning: no previous prototype for function 'mem_encrypt_init' [-Wmissing-prototypes]
void __init __weak mem_encrypt_init(void) { }
^
init/main.c:783:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void __init __weak mem_encrypt_init(void) { }
^
static
1 warning and 1 error generated.
--
In file included from kernel/delayacct.c:14:
>> include/linux/delayacct.h:48:6: error: duplicate member 'freepages_start'
u64 freepages_start;
^
include/linux/delayacct.h:39:6: note: previous declaration is here
u64 freepages_start;
^
1 error generated.
--
In file included from mm/page_alloc.c:77:
>> include/linux/delayacct.h:48:6: error: duplicate member 'freepages_start'
u64 freepages_start;
^
include/linux/delayacct.h:39:6: note: previous declaration is here
u64 freepages_start;
^
mm/page_alloc.c:3820:15: warning: no previous prototype for function 'should_fail_alloc_page' [-Wmissing-prototypes]
noinline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
^
mm/page_alloc.c:3820:10: note: declare 'static' if the function is not intended to be used outside of this translation unit
noinline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
^
static
1 warning and 1 error generated.
--
In file included from kernel/sched/core.c:13:
In file included from kernel/sched/sched.h:47:
>> include/linux/delayacct.h:48:6: error: duplicate member 'freepages_start'
u64 freepages_start;
^
include/linux/delayacct.h:39:6: note: previous declaration is here
u64 freepages_start;
^
kernel/sched/core.c:3450:6: warning: no previous prototype for function 'sched_set_stop_task' [-Wmissing-prototypes]
void sched_set_stop_task(int cpu, struct task_struct *stop)
^
kernel/sched/core.c:3450:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void sched_set_stop_task(int cpu, struct task_struct *stop)
^
static
1 warning and 1 error generated.
--
In file included from kernel/sched/fair.c:23:
In file included from kernel/sched/sched.h:47:
>> include/linux/delayacct.h:48:6: error: duplicate member 'freepages_start'
u64 freepages_start;
^
include/linux/delayacct.h:39:6: note: previous declaration is here
u64 freepages_start;
^
kernel/sched/fair.c:11094:6: warning: no previous prototype for function 'task_vruntime_update' [-Wmissing-prototypes]
void task_vruntime_update(struct rq *rq, struct task_struct *p, bool in_fi)
^
kernel/sched/fair.c:11094:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
void task_vruntime_update(struct rq *rq, struct task_struct *p, bool in_fi)
^
static
1 warning and 1 error generated.
--
In file included from kernel/sched/rt.c:6:
In file included from kernel/sched/sched.h:47:
>> include/linux/delayacct.h:48:6: error: duplicate member 'freepages_start'
u64 freepages_start;
^
include/linux/delayacct.h:39:6: note: previous declaration is here
u64 freepages_start;
^
kernel/sched/rt.c:675:6: warning: no previous prototype for function 'sched_rt_bandwidth_account' [-Wmissing-prototypes]
bool sched_rt_bandwidth_account(struct rt_rq *rt_rq)
^
kernel/sched/rt.c:675:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
bool sched_rt_bandwidth_account(struct rt_rq *rt_rq)
^
static
1 warning and 1 error generated.


vim +/freepages_start +48 include/linux/delayacct.h

11
12 #ifdef CONFIG_TASK_DELAY_ACCT
13 struct task_delay_info {
14 raw_spinlock_t lock;
15
16 /* For each stat XXX, add following, aligned appropriately
17 *
18 * struct timespec XXX_start, XXX_end;
19 * u64 XXX_delay;
20 * u32 XXX_count;
21 *
22 * Atomicity of updates to XXX_delay, XXX_count protected by
23 * single lock above (split into XXX_lock if contention is an issue).
24 */
25
26 /*
27 * XXX_count is incremented on every XXX operation, the delay
28 * associated with the operation is added to XXX_delay.
29 * XXX_delay contains the accumulated delay time in nanoseconds.
30 */
31 u64 blkio_start;
32 u64 blkio_delay; /* wait for sync block io completion */
33 u64 swapin_start;
34 u64 swapin_delay; /* wait for swapin */
35 u32 blkio_count; /* total count of the number of sync block */
36 /* io operations performed */
37 u32 swapin_count; /* total count of swapin */
38
39 u64 freepages_start;
40 u64 freepages_delay; /* wait for memory reclaim */
41
42 u64 thrashing_start;
43 u64 thrashing_delay; /* wait for thrashing page */
44
45 u64 compact_start;
46 u64 compact_delay; /* wait for memory compact */
47
> 48 u64 freepages_start;
49 u32 freepages_count; /* total count of memory reclaim */
50 u32 thrashing_count; /* total count of thrash waits */
51 u32 compact_count; /* total count of memory compact */
52 };
53 #endif
54

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]

2021-12-04 11:23:37

by Yong Wang

[permalink] [raw]
Subject: Re: [PATCH linux-next] delayacct: track delays from memory compact

Sorry, the patch has something wrong.
I'll resend the patch later.

Thanks!

Andrew Morton <[email protected]> 于2021年12月4日周六 05:02写道:
>
> On Fri, 3 Dec 2021 06:37:52 -0800 [email protected] wrote:
>
> > From: wangyong <[email protected]>
> >
> > Delay accounting does not track the delay of memory compact.
> > When there is not enough free memory, tasks can spend
> > a amount of their time waiting for memory compact.
> >
> > To get the impact of tasks in direct memory compact, measure
> > the delay when allocating memory through memory compact.
> >
> > ...
> >
> > --- a/include/linux/delayacct.h
> > +++ b/include/linux/delayacct.h
> > @@ -42,8 +42,13 @@ struct task_delay_info {
> > u64 thrashing_start;
> > u64 thrashing_delay; /* wait for thrashing page */
> >
> > + u64 compact_start;
> > + u64 compact_delay; /* wait for memory compact */
> > +
> > + u64 freepages_start;
>
> task_delay_info already has a freepages_start, so it fails to compile.
>
> Did you send the correct version?
>