mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-10-03 23:16:55 +00:00

Sometimes, application responses become bad under heavy memory load.
Applications take a bit time to reclaim memory. The statistics, how long
memory reclaim takes, will be useful to measure memory usage.
This patch adds accounting memory reclaim to per-task-delay-accounting for
accounting the time of do_try_to_free_pages().
<i.e>
- When System is under low memory load,
memory reclaim may not occur.
$ free
total used free shared buffers cached
Mem: 8197800 1577300 6620500 0 4808 1516724
-/+ buffers/cache: 55768 8142032
Swap: 16386292 0 16386292
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 0 5069748 10612 3014060 0 0 0 0 3 26 0 0 100 0
0 0 0 5069748 10612 3014060 0 0 0 0 4 22 0 0 100 0
0 0 0 5069748 10612 3014060 0 0 0 0 3 18 0 0 100 0
Measure the time of tar command.
$ ls -s test.dat
1501472 test.dat
$ time tar cvf test.tar test.dat
real 0m13.388s
user 0m0.116s
sys 0m5.304s
$ ./delayget -d -p <pid>
CPU count real total virtual total delay total
428 5528345500 5477116080 62749891
IO count delay total
338 8078977189
SWAP count delay total
0 0
RECLAIM count delay total
0 0
- When system is under heavy memory load
memory reclaim may occur.
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 0 7159032 49724 1812 3012 0 0 0 0 3 24 0 0 100 0
0 0 7159032 49724 1812 3012 0 0 0 0 4 24 0 0 100 0
0 0 7159032 49848 1812 3012 0 0 0 0 3 22 0 0 100 0
In this case, one process uses more 8G memory
by execution of malloc() and memset().
$ time tar cvf test.tar test.dat
real 1m38.563s <- increased by 85 sec
user 0m0.140s
sys 0m7.060s
$ ./delayget -d -p <pid>
CPU count real total virtual total delay total
9021 7140446250 7315277975 923201824
IO count delay total
8965 90466349669
SWAP count delay total
3 21036367
RECLAIM count delay total
740 61011951153
In the later case, the value of RECLAIM is increasing.
So, taskstats can show how much memory reclaim influences TAT.
Signed-off-by: Keika Kobayashi <kobayashi.kk@ncos.nec.co.jp>
Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujistu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
154 lines
4.0 KiB
C
154 lines
4.0 KiB
C
/* delayacct.h - per-task delay accounting
|
|
*
|
|
* Copyright (C) Shailabh Nagar, IBM Corp. 2006
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
|
* the GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#ifndef _LINUX_DELAYACCT_H
|
|
#define _LINUX_DELAYACCT_H
|
|
|
|
#include <linux/sched.h>
|
|
#include <linux/taskstats_kern.h>
|
|
|
|
/*
|
|
* Per-task flags relevant to delay accounting
|
|
* maintained privately to avoid exhausting similar flags in sched.h:PF_*
|
|
* Used to set current->delays->flags
|
|
*/
|
|
#define DELAYACCT_PF_SWAPIN 0x00000001 /* I am doing a swapin */
|
|
#define DELAYACCT_PF_BLKIO 0x00000002 /* I am waiting on IO */
|
|
|
|
#ifdef CONFIG_TASK_DELAY_ACCT
|
|
|
|
extern int delayacct_on; /* Delay accounting turned on/off */
|
|
extern struct kmem_cache *delayacct_cache;
|
|
extern void delayacct_init(void);
|
|
extern void __delayacct_tsk_init(struct task_struct *);
|
|
extern void __delayacct_tsk_exit(struct task_struct *);
|
|
extern void __delayacct_blkio_start(void);
|
|
extern void __delayacct_blkio_end(void);
|
|
extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
|
|
extern __u64 __delayacct_blkio_ticks(struct task_struct *);
|
|
extern void __delayacct_freepages_start(void);
|
|
extern void __delayacct_freepages_end(void);
|
|
|
|
static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
|
|
{
|
|
if (p->delays)
|
|
return (p->delays->flags & DELAYACCT_PF_BLKIO);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static inline void delayacct_set_flag(int flag)
|
|
{
|
|
if (current->delays)
|
|
current->delays->flags |= flag;
|
|
}
|
|
|
|
static inline void delayacct_clear_flag(int flag)
|
|
{
|
|
if (current->delays)
|
|
current->delays->flags &= ~flag;
|
|
}
|
|
|
|
static inline void delayacct_tsk_init(struct task_struct *tsk)
|
|
{
|
|
/* reinitialize in case parent's non-null pointer was dup'ed*/
|
|
tsk->delays = NULL;
|
|
if (delayacct_on)
|
|
__delayacct_tsk_init(tsk);
|
|
}
|
|
|
|
/* Free tsk->delays. Called from bad fork and __put_task_struct
|
|
* where there's no risk of tsk->delays being accessed elsewhere
|
|
*/
|
|
static inline void delayacct_tsk_free(struct task_struct *tsk)
|
|
{
|
|
if (tsk->delays)
|
|
kmem_cache_free(delayacct_cache, tsk->delays);
|
|
tsk->delays = NULL;
|
|
}
|
|
|
|
static inline void delayacct_blkio_start(void)
|
|
{
|
|
delayacct_set_flag(DELAYACCT_PF_BLKIO);
|
|
if (current->delays)
|
|
__delayacct_blkio_start();
|
|
}
|
|
|
|
static inline void delayacct_blkio_end(void)
|
|
{
|
|
if (current->delays)
|
|
__delayacct_blkio_end();
|
|
delayacct_clear_flag(DELAYACCT_PF_BLKIO);
|
|
}
|
|
|
|
static inline int delayacct_add_tsk(struct taskstats *d,
|
|
struct task_struct *tsk)
|
|
{
|
|
if (!delayacct_on || !tsk->delays)
|
|
return 0;
|
|
return __delayacct_add_tsk(d, tsk);
|
|
}
|
|
|
|
static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
|
|
{
|
|
if (tsk->delays)
|
|
return __delayacct_blkio_ticks(tsk);
|
|
return 0;
|
|
}
|
|
|
|
static inline void delayacct_freepages_start(void)
|
|
{
|
|
if (current->delays)
|
|
__delayacct_freepages_start();
|
|
}
|
|
|
|
static inline void delayacct_freepages_end(void)
|
|
{
|
|
if (current->delays)
|
|
__delayacct_freepages_end();
|
|
}
|
|
|
|
#else
|
|
static inline void delayacct_set_flag(int flag)
|
|
{}
|
|
static inline void delayacct_clear_flag(int flag)
|
|
{}
|
|
static inline void delayacct_init(void)
|
|
{}
|
|
static inline void delayacct_tsk_init(struct task_struct *tsk)
|
|
{}
|
|
static inline void delayacct_tsk_free(struct task_struct *tsk)
|
|
{}
|
|
static inline void delayacct_blkio_start(void)
|
|
{}
|
|
static inline void delayacct_blkio_end(void)
|
|
{}
|
|
static inline int delayacct_add_tsk(struct taskstats *d,
|
|
struct task_struct *tsk)
|
|
{ return 0; }
|
|
static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
|
|
{ return 0; }
|
|
static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
|
|
{ return 0; }
|
|
static inline void delayacct_freepages_start(void)
|
|
{}
|
|
static inline void delayacct_freepages_end(void)
|
|
{}
|
|
|
|
#endif /* CONFIG_TASK_DELAY_ACCT */
|
|
|
|
#endif
|