3 # The MIT License (MIT)
5 # Copyright (C) 2015 - Julien Desfossez <jdesfossez@efficios.com>
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 from .command
import Command
26 import lttnganalyses
.cputop
27 from linuxautomaton
import common
28 from ascii_graph
import Pyasciigraph
32 class Cputop(Command
):
34 _DESC
= """The cputop command."""
37 super().__init
__(self
._add
_arguments
, enable_proc_filter_args
=True)
39 def _validate_transform_args(self
):
43 # parse arguments first
45 # validate, transform and save specific arguments
46 self
._validate
_transform
_args
()
49 # create the appropriate analysis/analyses
50 self
._create
_analysis
()
52 self
._run
_analysis
(self
._reset
_total
, self
._refresh
)
56 self
._print
_results
(self
.start_ns
, self
.trace_end_ts
, final
=1)
60 def _create_analysis(self
):
61 self
._analysis
= lttnganalyses
.cputop
.Cputop(self
._automaton
.state
)
63 def _compute_stats(self
):
64 self
.state
= self
._automaton
.state
65 for cpu
in self
.state
.cpus
.keys():
66 current_cpu
= self
.state
.cpus
[cpu
]
67 total_ns
= self
.end_ns
- self
.start_ns
68 if current_cpu
.start_task_ns
!= 0:
69 current_cpu
.cpu_ns
+= self
.end_ns
- current_cpu
.start_task_ns
70 cpu_total_ns
= current_cpu
.cpu_ns
71 current_cpu
.cpu_pc
= (cpu_total_ns
* 100)/total_ns
72 if current_cpu
.current_tid
>= 0:
73 self
.state
.tids
[current_cpu
.current_tid
].cpu_ns
+= \
74 self
.end_ns
- current_cpu
.start_task_ns
76 def _reset_total(self
, start_ts
):
77 self
.state
= self
._automaton
.state
78 for cpu
in self
.state
.cpus
.keys():
79 current_cpu
= self
.state
.cpus
[cpu
]
80 current_cpu
.cpu_ns
= 0
81 if current_cpu
.start_task_ns
!= 0:
82 current_cpu
.start_task_ns
= start_ts
83 if current_cpu
.current_tid
>= 0:
84 self
.state
.tids
[current_cpu
.current_tid
].last_sched
= start_ts
85 for tid
in self
.state
.tids
.keys():
86 self
.state
.tids
[tid
].cpu_ns
= 0
87 self
.state
.tids
[tid
].migrate_count
= 0
88 self
.state
.tids
[tid
].read
= 0
89 self
.state
.tids
[tid
].write
= 0
90 for syscall
in self
.state
.tids
[tid
].syscalls
.keys():
91 self
.state
.tids
[tid
].syscalls
[syscall
].count
= 0
93 def _refresh(self
, begin
, end
):
95 self
._print
_results
(begin
, end
, final
=0)
96 self
._reset
_total
(end
)
98 def _print_results(self
, begin_ns
, end_ns
, final
=0):
99 # print('event count: {}'.format(self._analysis.event_count))
101 limit
= self
._arg
_limit
102 total_ns
= end_ns
- begin_ns
103 graph
= Pyasciigraph()
105 print('Timerange: [%s, %s]' % (
106 common
.ns_to_hour_nsec(begin_ns
, gmt
=self
._arg
_gmt
,
108 common
.ns_to_hour_nsec(end_ns
, gmt
=self
._arg
_gmt
,
110 for tid
in sorted(self
.state
.tids
.values(),
111 key
=operator
.attrgetter('cpu_ns'), reverse
=True):
112 if self
._arg
_proc
_list
and tid
.comm
not in self
._arg
_proc
_list
:
116 pc
= float("%0.02f" % ((tid
.cpu_ns
* 100) / total_ns
))
117 if tid
.migrate_count
> 0:
118 migrations
= ", %d migrations" % (tid
.migrate_count
)
121 values
.append(("%s (%d)%s" % (tid
.comm
, tid
.tid
, migrations
), pc
))
123 if limit
> 0 and count
>= limit
:
125 for line
in graph
.graph("Per-TID CPU Usage", values
, unit
=" %"):
130 for cpu
in sorted(self
.state
.cpus
.values(),
131 key
=operator
.attrgetter('cpu_ns'), reverse
=True):
132 cpu_pc
= float("%0.02f" % cpu
.cpu_pc
)
133 total_cpu_pc
+= cpu_pc
134 values
.append(("CPU %d" % cpu
.cpu_id
, cpu_pc
))
135 for line
in graph
.graph("Per-CPU Usage", values
, unit
=" %"):
137 print("\nTotal CPU Usage: %0.02f%%\n" %
138 (total_cpu_pc
/ len(self
.state
.cpus
.keys())))
140 def _add_arguments(self
, ap
):
This page took 0.034161 seconds and 5 git commands to generate.