Cpu statistics accounting based on Paul Menage patches
PATCH 1/1 Cpu statistics accounting based on Paul Menage patches
Provides a per-container statistics concerning the numbers of tasks in various states, system and user times, etc. Patch is inspired by Paul's example of the used CPU time accounting. Although this patch is independent from Paul's example to make it possible playing with them separately.
Based on Paul Menage containers v8.
One thing left is the idle time accounting. The problem in idle time accounting is that the algorithm used to calculate global idle time is useless. When system is loaded with tasks (and thus have 0% idle) some containers may be idle, i.e. no tasks run within a container.
A known feature of this patch is that the numbers of tasks shown for top container are not 100% true, as by the time the top container is created system is already running. Probably this statistics is simply not needed for top container.
include/linux/cpu_acct.h renamed from include/linux/cpu_acct.h.taskstats +46 -0
@@ -0,0 +1,46 @@ +#ifndef _LINUX_CPU_ACCT_H +#define _LINUX_CPU_ACCT_H + +#include <linux/container.h> + +#ifdef CONFIG_CPU_ACCT_CONTAINER +void container_nr_running_inc (struct task_struct *); +void container_nr_running_dec (struct task_struct *); + +void container_nr_unint_inc (struct task_struct *); +void container_nr_unint_dec (struct task_struct *); + +void container_nr_sleeping_inc (struct task_struct *); +void container_nr_sleeping_dec (struct task_struct *); + +void container_nr_stopped_inc (struct task_struct *); +void container_nr_stopped_dec (struct task_struct *); + +void container_nr_iowait_inc (struct task_struct *); +void container_nr_iowait_dec (struct task_struct *); + +void container_add_time_nice (struct task_struct *,cputime64_t ); +void container_add_time_user (struct task_struct *,cputime64_t ); +void container_add_time_system (struct task_struct *,cputime64_t ); +#else +#define container_nr_running_inc (p) do { } while (0) +#define container_nr_running_dec (p) do { } while (0) + +#define container_nr_unint_inc (p) do { } while (0) +#define container_nr_unint_dec (p) do { } while (0) + +#define container_nr_sleeping_inc (p) do { } while (0) +#define container_nr_sleeping_dec (p) do { } while (0) + +#define container_nr_stopped_inc (p) do { } while (0) +#define container_nr_stopped_dec (p) do { } while (0) + +#define container_nr_iowait_inc (p) do { } while (0) +#define container_nr_iowait_dec (p) do { } while (0) + +#define container_add_time_nice (p, time) do { } while (0) +#define container_add_time_user (p, time) do { } while (0) +#define container_add_time_system (p, time) do { } while (0) +#endif + +#endif
include/linux/container_subsys.h renamed from include/linux/container_subsys.h.taskstats +4 -0
@@ -9,6 +9,10 @@ SUBSYS(cpuset)#endif +#ifdef CONFIG_CPU_ACCT_CONTAINER +SUBSYS(cpuacct) +#endif +/* */ /* */
include/linux/sched.h renamed from include/linux/sched.h.taskstats +3 -0
@@ -1052,6 +1052,9 @@ struct task_struct {#ifdef CONFIG_FAULT_INJECTION int make_it_fail;#endif +#ifdef CONFIG_CPU_ACCT_CONTAINER +int iowait; +#endif };static inline pid_t process_group (struct task_struct *tsk)
init/Kconfig renamed from init/Kconfig.taskstats +7 -0
@@ -253,6 +253,13 @@ config CPUSETS Say N if unsure. +config CPU_ACCT_CONTAINER + bool "CPU usage accounting container" + select CONTAINERS + help + Provides a per-container statistics concerning the numbers of tasks + in various states, system and user times, etc + config SYSFS_DEPRECATED bool "Create deprecated sysfs files" default y
kernel/cpu_acct.c renamed from kernel/cpu_acct.c.taskstats +346 -0
346 lines not on this page · raw message
kernel/sched.c renamed from kernel/sched.c.taskstats +28 -3
@@ -56,6 +56,8 @@#include <asm/unistd.h> +#include <linux/cpu_acct.h> +/* * Convert user-nice values [ -20 ... 0 ... 19 ] * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
@@ -794,12 +796,14 @@ dec_raw_weighted_load(struct rq *rq, constatic inline void inc_nr_running (struct task_struct *p,struct rq *rq) { rq->nr_running++; +container_nr_running_inc (p);inc_raw_weighted_load (rq, p); }static inline void dec_nr_running (struct task_struct *p,struct rq *rq) { rq->nr_running--; +container_nr_running_dec (p);dec_raw_weighted_load (rq, p); }
@@ -1004,6 +1008,13 @@ static void deactivate_task(struct task_dec_nr_running (p, rq);dequeue_task (p, p->array); p->array =NULL ; + +if (p->state ==TASK_UNINTERRUPTIBLE ) +container_nr_unint_inc (p); +else if (p->state ==TASK_INTERRUPTIBLE ) +container_nr_sleeping_inc (p); +else if (p->state ==TASK_STOPPED ) +container_nr_stopped_inc (p); }/*
@@ -1516,12 +1527,17 @@ out_activate:#endif /* CONFIG_SMP */ if (old_state ==TASK_UNINTERRUPTIBLE ) { rq->nr_uninterruptible--; +container_nr_unint_dec (p);/* * Tasks on involuntary sleep don't earn * sleep_avg beyond just interactive state. */ p->sleep_type =SLEEP_NONINTERACTIVE ; - }else + }else { +if (old_state ==TASK_INTERRUPTIBLE ) +container_nr_sleeping_dec (p); +else if (old_state ==TASK_STOPPED ) +container_nr_stopped_dec (p);/* * Tasks that have marked their sleep as noninteractive get
@@ -1530,6 +1546,7 @@ out_activate:*/ if (old_state &TASK_NONINTERACTIVE ) p->sleep_type =SLEEP_NONINTERACTIVE ; + }activate_task (p, rq, cpu == this_cpu);
@@ -3071,10 +3088,13 @@ void account_user_time(struct task_struc/* Add user time to cpustat. */ tmp =cputime_to_cputime64 (cputime); -if (TASK_NICE (p) >0 ) +if (TASK_NICE (p) >0 ) { cpustat->nice =cputime64_add (cpustat->nice, tmp); -else +container_add_time_nice (p, tmp); + }else { cpustat->user =cputime64_add (cpustat->user, tmp); +container_add_time_user (p, tmp); + } }/*
@@ -3091,6 +3111,7 @@ void account_system_time(struct task_strcputime64_t tmp; p->stime =cputime_add (p->stime, cputime); +container_add_time_system (p,cputime_to_cputime64 (cputime));/* Add system time to cpustat. */ tmp =cputime_to_cputime64 (cputime);
@@ -4717,7 +4738,9 @@ void __sched io_schedule(void)delayacct_blkio_start ();atomic_inc (&rq->nr_iowait); +container_nr_iowait_inc (current);schedule (); +container_nr_iowait_dec (current);atomic_dec (&rq->nr_iowait);delayacct_blkio_end (); }
@@ -4730,7 +4753,9 @@ long __sched io_schedule_timeout(long tidelayacct_blkio_start ();atomic_inc (&rq->nr_iowait); +container_nr_iowait_inc (current); ret =schedule_timeout (timeout); +container_nr_iowait_dec (current);atomic_dec (&rq->nr_iowait);delayacct_blkio_end ();return ret;
kernel/Makefile renamed from kernel/Makefile.taskstats +1 -0
@@ -51,6 +51,7 @@ obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_UTS_NS) += utsname.o obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o +obj-$(CONFIG_CPU_ACCT_CONTAINER) += cpu_acct.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
Quoted 5 lines · On Wed, 11 Apr 2007 19:02:27 +0400 Pavel Emelianov <[email protected]> wrote:
Provides a per-container statistics concerning the numbers of tasks in various states, system and user times, etc. Patch is inspired by Paul's example of the used CPU time accounting. Although this patch is independent from Paul's example to make it possible playing with them separately.
Why is this actually needed? If userspace has a list of the tasks which are in a particular container, it can run around and add up the stats for those tasks without kernel changes?
It's a bit irksome that we have so much accounting of this form in core kernel, yet we have to go and add a completely new implementation to create something which is similar to what we already have. But I don't immediately see a fix for that. Apart from paragraph #1 ;)
Should there be linkage between per-container stats and delivery-via-taskstats? I can't think of one, really.
You have cpu stats. Later, presumably, we'll need IO stats, MM stats, context-switch stats, number-of-syscall stats, etc, etc. Are we going to reimplement all of those things as well? See paragraph #1!
Bottom line: I think we seriously need to find some way of consolidating per-container stats with our present per-task stats. Perhaps we should instead be looking at ways in which we can speed up paragraph #1.
Quoted 9 lines · Andrew Morton
Quoted 5 lines · On Wed, 11 Apr 2007 19:02:27 +0400 Pavel Emelianov <[email protected]> wrote:
Provides a per-container statistics concerning the numbers of tasks in various states, system and user times, etc. Patch is inspired by Paul's example of the used CPU time accounting. Although this patch is independent from Paul's example to make it possible playing with them separately.
Quoted 3 lines
Why is this actually needed? If userspace has a list of the tasks which are in a particular container, it can run around and add up the stats for those tasks without kernel changes?
Well, the per-conainer nr_running and nr_uninterruptibe accounting is the only way to calculate loadavg and idle time for *container*.
Look, the idle time for container (for one CPU) is the time when no tasks within this container were ready to run on this CPU. That's the definition implicitly used in global idle time accounting. Current per-rq counters can't solve this problem and neither can the update_process_times() method.
The same with loadavg. To calculate it per-container we need to have some nr_active_in_container() function, but it must work faster than walking the tasks within the container.
Quoted 3 lines
It's a bit irksome that we have so much accounting of this form in core kernel, yet we have to go and add a completely new implementation to create something which is similar to what we already have. But I don't
Creating something similar would be a bit problematic.
Some stats are stored on task_struct some are pointed from a signal_struct, some are reported via /proc files, some via netlink sockets, some statistics can be per-task some cannot.
On the other hand containers provide a generic way to group the tasks and report the statistics for it. So we can keep the stats in one place and report in a similar way.
Quoted 4 lines
immediately see a fix for that. Apart from paragraph #1 ;)
Should there be linkage between per-container stats and delivery-via-taskstats? I can't think of one, really.
Since this patch uses Paul's containers to define the term of a group it uses the provided facilities for reporting the results :)
Quoted 3 lines
You have cpu stats. Later, presumably, we'll need IO stats, MM stats, context-switch stats, number-of-syscall stats, etc, etc. Are we going to reimplement all of those things as well? See paragraph #1!
Not reimplement, but collect it in two or three stages: per-task (if needed), per-container and overall.
There are two ways of doing so:
1. collect it on-demand by walking tasks in container;
2. collect it on-the-fly reporting the values accumulated.
The first way is less intrusive, while the second one is probably faster. Moreover - the first way is inapplicable to some statistics, e.g. loadavg. The same stays true for overall statistics - we may report nr_running by walking tasklist each time, but it is not used. We suggest to make it the same way in per-container accounting as well.
Quoted 9 lines
Bottom line: I think we seriously need to find some way of consolidating per-container stats with our present per-task stats. Perhaps we should instead be looking at ways in which we can speed up paragraph #1. -
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Quoted 21 lines · Andrew Morton
Quoted 5 lines · On Wed, 11 Apr 2007 19:02:27 +0400 Pavel Emelianov <[email protected]> wrote:
Provides a per-container statistics concerning the numbers of tasks in various states, system and user times, etc. Patch is inspired by Paul's example of the used CPU time accounting. Although this patch is independent from Paul's example to make it possible playing with them separately.
Why is this actually needed? If userspace has a list of the tasks which are in a particular container, it can run around and add up the stats for those tasks without kernel changes?
It's a bit irksome that we have so much accounting of this form in core kernel, yet we have to go and add a completely new implementation to create something which is similar to what we already have. But I don't immediately see a fix for that. Apart from paragraph #1 ;)
Should there be linkage between per-container stats and delivery-via-taskstats? I can't think of one, really.
Quoted 7 lines
You have cpu stats. Later, presumably, we'll need IO stats, MM stats, context-switch stats, number-of-syscall stats, etc, etc. Are we going to reimplement all of those things as well? See paragraph #1!
Bottom line: I think we seriously need to find some way of consolidating per-container stats with our present per-task stats. Perhaps we should instead be looking at ways in which we can speed up paragraph #1.
This should be easy to build. per container stats can live in parallel with per-task stats, but they can use the same general mechanism for data communication to user space.
Signature · 4 lines
Warm Regards, Balbir Singh Linux Technology Center IBM, ISTL