Skip to content

Commit 662ce1d

Browse files
yangyang20220519akpm00
authored andcommitted
delayacct: track delays from write-protect copy
Delay accounting does not track the delay of write-protect copy. When tasks trigger many write-protect copys(include COW and unsharing of anonymous pages[1]), it may spend a amount of time waiting for them. To get the delay of tasks in write-protect copy, could help users to evaluate the impact of using KSM or fork() or GUP. Also update tools/accounting/getdelays.c: / # ./getdelays -dl -p 231 print delayacct stats ON listen forever PID 231 CPU count real total virtual total delay total delay average 6247 1859000000 2154070021 1674255063 0.268ms IO count delay total delay average 0 0 0ms SWAP count delay total delay average 0 0 0ms RECLAIM count delay total delay average 0 0 0ms THRASHING count delay total delay average 0 0 0ms COMPACT count delay total delay average 3 72758 0ms WPCOPY count delay total delay average 3635 271567604 0ms [1] commit 31cc5bc4af70("mm: support GUP-triggered unsharing of anonymous pages") Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Yang Yang <[email protected]> Reviewed-by: David Hildenbrand <[email protected]> Reviewed-by: Jiang Xuexin <[email protected]> Reviewed-by: Ran Xiaokai <[email protected]> Reviewed-by: wangyong <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Balbir Singh <[email protected]> Cc: Mike Kravetz <[email protected]> Cc: Stephen Rothwell <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 54eb846 commit 662ce1d

File tree

7 files changed

+76
-3
lines changed

7 files changed

+76
-3
lines changed

Documentation/accounting/delay-accounting.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ c) swapping in pages
1515
d) memory reclaim
1616
e) thrashing page cache
1717
f) direct compact
18+
g) write-protect copy
1819

1920
and makes these statistics available to userspace through
2021
the taskstats interface.
@@ -48,7 +49,7 @@ this structure. See
4849
for a description of the fields pertaining to delay accounting.
4950
It will generally be in the form of counters returning the cumulative
5051
delay seen for cpu, sync block I/O, swapin, memory reclaim, thrash page
51-
cache, direct compact etc.
52+
cache, direct compact, write-protect copy etc.
5253

5354
Taking the difference of two successive readings of a given
5455
counter (say cpu_delay_total) for a task will give the delay
@@ -117,6 +118,8 @@ Get sum of delays, since system boot, for all pids with tgid 5::
117118
0 0 0ms
118119
COMPACT count delay total delay average
119120
0 0 0ms
121+
WPCOPY count delay total delay average
122+
0 0 0ms
120123

121124
Get IO accounting for pid 1, it works only with -p::
122125

include/linux/delayacct.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,13 @@ struct task_delay_info {
4545
u64 compact_start;
4646
u64 compact_delay; /* wait for memory compact */
4747

48+
u64 wpcopy_start;
49+
u64 wpcopy_delay; /* wait for write-protect copy */
50+
4851
u32 freepages_count; /* total count of memory reclaim */
4952
u32 thrashing_count; /* total count of thrash waits */
5053
u32 compact_count; /* total count of memory compact */
54+
u32 wpcopy_count; /* total count of write-protect copy */
5155
};
5256
#endif
5357

@@ -75,6 +79,8 @@ extern void __delayacct_swapin_start(void);
7579
extern void __delayacct_swapin_end(void);
7680
extern void __delayacct_compact_start(void);
7781
extern void __delayacct_compact_end(void);
82+
extern void __delayacct_wpcopy_start(void);
83+
extern void __delayacct_wpcopy_end(void);
7884

7985
static inline void delayacct_tsk_init(struct task_struct *tsk)
8086
{
@@ -191,6 +197,24 @@ static inline void delayacct_compact_end(void)
191197
__delayacct_compact_end();
192198
}
193199

200+
static inline void delayacct_wpcopy_start(void)
201+
{
202+
if (!static_branch_unlikely(&delayacct_key))
203+
return;
204+
205+
if (current->delays)
206+
__delayacct_wpcopy_start();
207+
}
208+
209+
static inline void delayacct_wpcopy_end(void)
210+
{
211+
if (!static_branch_unlikely(&delayacct_key))
212+
return;
213+
214+
if (current->delays)
215+
__delayacct_wpcopy_end();
216+
}
217+
194218
#else
195219
static inline void delayacct_init(void)
196220
{}
@@ -225,6 +249,10 @@ static inline void delayacct_compact_start(void)
225249
{}
226250
static inline void delayacct_compact_end(void)
227251
{}
252+
static inline void delayacct_wpcopy_start(void)
253+
{}
254+
static inline void delayacct_wpcopy_end(void)
255+
{}
228256

229257
#endif /* CONFIG_TASK_DELAY_ACCT */
230258

include/uapi/linux/taskstats.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
*/
3535

3636

37-
#define TASKSTATS_VERSION 12
37+
#define TASKSTATS_VERSION 13
3838
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
3939
* in linux/sched.h */
4040

@@ -194,6 +194,10 @@ struct taskstats {
194194
__u64 ac_exe_dev; /* program binary device ID */
195195
__u64 ac_exe_inode; /* program binary inode number */
196196
/* v12 end */
197+
198+
/* v13: Delay waiting for write-protect copy */
199+
__u64 wpcopy_count;
200+
__u64 wpcopy_delay_total;
197201
};
198202

199203

kernel/delayacct.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,14 @@ int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
177177
d->thrashing_delay_total = (tmp < d->thrashing_delay_total) ? 0 : tmp;
178178
tmp = d->compact_delay_total + tsk->delays->compact_delay;
179179
d->compact_delay_total = (tmp < d->compact_delay_total) ? 0 : tmp;
180+
tmp = d->wpcopy_delay_total + tsk->delays->wpcopy_delay;
181+
d->wpcopy_delay_total = (tmp < d->wpcopy_delay_total) ? 0 : tmp;
180182
d->blkio_count += tsk->delays->blkio_count;
181183
d->swapin_count += tsk->delays->swapin_count;
182184
d->freepages_count += tsk->delays->freepages_count;
183185
d->thrashing_count += tsk->delays->thrashing_count;
184186
d->compact_count += tsk->delays->compact_count;
187+
d->wpcopy_count += tsk->delays->wpcopy_count;
185188
raw_spin_unlock_irqrestore(&tsk->delays->lock, flags);
186189

187190
return 0;
@@ -249,3 +252,16 @@ void __delayacct_compact_end(void)
249252
&current->delays->compact_delay,
250253
&current->delays->compact_count);
251254
}
255+
256+
void __delayacct_wpcopy_start(void)
257+
{
258+
current->delays->wpcopy_start = local_clock();
259+
}
260+
261+
void __delayacct_wpcopy_end(void)
262+
{
263+
delayacct_end(&current->delays->lock,
264+
&current->delays->wpcopy_start,
265+
&current->delays->wpcopy_delay,
266+
&current->delays->wpcopy_count);
267+
}

mm/hugetlb.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/cma.h>
3333
#include <linux/migrate.h>
3434
#include <linux/nospec.h>
35+
#include <linux/delayacct.h>
3536

3637
#include <asm/page.h>
3738
#include <asm/pgalloc.h>
@@ -5230,6 +5231,8 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
52305231
pte = huge_ptep_get(ptep);
52315232
old_page = pte_page(pte);
52325233

5234+
delayacct_wpcopy_start();
5235+
52335236
retry_avoidcopy:
52345237
/*
52355238
* If no-one else is actually using this page, we're the exclusive
@@ -5240,6 +5243,8 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
52405243
page_move_anon_rmap(old_page, vma);
52415244
if (likely(!unshare))
52425245
set_huge_ptep_writable(vma, haddr, ptep);
5246+
5247+
delayacct_wpcopy_end();
52435248
return 0;
52445249
}
52455250
VM_BUG_ON_PAGE(PageAnon(old_page) && PageAnonExclusive(old_page),
@@ -5309,6 +5314,7 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
53095314
* race occurs while re-acquiring page table
53105315
* lock, and our job is done.
53115316
*/
5317+
delayacct_wpcopy_end();
53125318
return 0;
53135319
}
53145320

@@ -5367,6 +5373,8 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
53675373
put_page(old_page);
53685374

53695375
spin_lock(ptl); /* Caller expects lock to be held */
5376+
5377+
delayacct_wpcopy_end();
53705378
return ret;
53715379
}
53725380

mm/memory.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,6 +3090,8 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
30903090
int page_copied = 0;
30913091
struct mmu_notifier_range range;
30923092

3093+
delayacct_wpcopy_start();
3094+
30933095
if (unlikely(anon_vma_prepare(vma)))
30943096
goto oom;
30953097

@@ -3114,6 +3116,8 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
31143116
put_page(new_page);
31153117
if (old_page)
31163118
put_page(old_page);
3119+
3120+
delayacct_wpcopy_end();
31173121
return 0;
31183122
}
31193123
}
@@ -3220,12 +3224,16 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
32203224
free_swap_cache(old_page);
32213225
put_page(old_page);
32223226
}
3227+
3228+
delayacct_wpcopy_end();
32233229
return (page_copied && !unshare) ? VM_FAULT_WRITE : 0;
32243230
oom_free_new:
32253231
put_page(new_page);
32263232
oom:
32273233
if (old_page)
32283234
put_page(old_page);
3235+
3236+
delayacct_wpcopy_end();
32293237
return VM_FAULT_OOM;
32303238
}
32313239

tools/accounting/getdelays.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ static void print_delayacct(struct taskstats *t)
207207
"THRASHING%12s%15s%15s\n"
208208
" %15llu%15llu%15llums\n"
209209
"COMPACT %12s%15s%15s\n"
210+
" %15llu%15llu%15llums\n"
211+
"WPCOPY %12s%15s%15s\n"
210212
" %15llu%15llu%15llums\n",
211213
"count", "real total", "virtual total",
212214
"delay total", "delay average",
@@ -234,7 +236,11 @@ static void print_delayacct(struct taskstats *t)
234236
"count", "delay total", "delay average",
235237
(unsigned long long)t->compact_count,
236238
(unsigned long long)t->compact_delay_total,
237-
average_ms(t->compact_delay_total, t->compact_count));
239+
average_ms(t->compact_delay_total, t->compact_count),
240+
"count", "delay total", "delay average",
241+
(unsigned long long)t->wpcopy_count,
242+
(unsigned long long)t->wpcopy_delay_total,
243+
average_ms(t->wpcopy_delay_total, t->wpcopy_count));
238244
}
239245

240246
static void task_context_switch_counts(struct taskstats *t)

0 commit comments

Comments
 (0)