3 # Permission is hereby granted, free of charge, to any person obtaining a copy
4 # of this software and associated documentation files (the "Software"), to deal
5 # in the Software without restriction, including without limitation the rights
6 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 # copies of the Software, and to permit persons to whom the Software is
8 # furnished to do so, subject to the following conditions:
10 # The above copyright notice and this permission notice shall be included in
11 # all copies or substantial portions of the Software.
17 from babeltrace
import *
18 from LTTngAnalyzes
.common
import *
19 from LTTngAnalyzes
.sched
import *
20 from analyzes
import *
21 from ascii_graph
import Pyasciigraph
24 def __init__(self
, traces
):
25 self
.trace_start_ts
= 0
32 """Process the trace"""
37 sched
= Sched(self
.cpus
, self
.tids
)
38 for event
in self
.traces
.events
:
39 if self
.start_ns
== 0:
40 self
.start_ns
= event
.timestamp
41 if self
.trace_start_ts
== 0:
42 self
.trace_start_ts
= event
.timestamp
43 self
.end_ns
= event
.timestamp
44 self
.check_refresh(args
, event
)
45 self
.trace_end_ts
= event
.timestamp
47 if event
.name
== "sched_switch":
50 # stats for the whole trace
52 self
.output(args
, self
.trace_start_ts
, self
.trace_end_ts
, final
=1)
54 # stats only for the last segment
56 self
.output(args
, self
.start_ns
, self
.trace_end_ts
,
59 def check_refresh(self
, args
, event
):
60 """Check if we need to output something"""
63 event_sec
= event
.timestamp
/ NSEC_PER_SEC
64 if self
.current_sec
== 0:
65 self
.current_sec
= event_sec
66 elif self
.current_sec
!= event_sec
and \
67 (self
.current_sec
+ args
.refresh
) <= event_sec
:
69 self
.output(args
, self
.start_ns
, event
.timestamp
)
70 self
.reset_total(event
.timestamp
)
71 self
.current_sec
= event_sec
72 self
.start_ns
= event
.timestamp
74 def compute_stats(self
):
75 for cpu
in self
.cpus
.keys():
76 current_cpu
= self
.cpus
[cpu
]
77 total_ns
= self
.end_ns
- self
.start_ns
78 if current_cpu
.start_task_ns
!= 0:
79 current_cpu
.cpu_ns
+= self
.end_ns
- current_cpu
.start_task_ns
80 cpu_total_ns
= current_cpu
.cpu_ns
81 current_cpu
.cpu_pc
= (cpu_total_ns
* 100)/total_ns
82 if current_cpu
.current_tid
>= 0:
83 self
.tids
[current_cpu
.current_tid
].cpu_ns
+= \
84 self
.end_ns
- current_cpu
.start_task_ns
86 def output(self
, args
, begin_ns
, end_ns
, final
=0):
89 total_ns
= end_ns
- begin_ns
90 graph
= Pyasciigraph()
92 print('%s to %s' % (ns_to_asctime(begin_ns
), ns_to_asctime(end_ns
)))
93 for tid
in sorted(self
.tids
.values(),
94 key
=operator
.attrgetter('cpu_ns'), reverse
=True):
95 if len(args
.proc_list
) > 0 and tid
.comm
not in args
.proc_list
:
97 pc
= float("%0.02f" % ((tid
.cpu_ns
* 100) / total_ns
))
98 values
.append(("%s (%d)" % (tid
.comm
, tid
.tid
), pc
))
100 if limit
> 0 and count
>= limit
:
102 for line
in graph
.graph("Per-TID CPU Usage", values
):
106 nb_cpu
= len(self
.cpus
.keys())
107 for cpu
in sorted(self
.cpus
.values(),
108 key
=operator
.attrgetter('cpu_ns'), reverse
=True):
109 cpu_total_ns
= cpu
.cpu_ns
110 cpu_pc
= float("%0.02f" % cpu
.cpu_pc
)
111 values
.append(("CPU %d" % cpu
.cpu_id
, cpu_pc
))
112 for line
in graph
.graph("Per-CPU Usage", values
):
115 def reset_total(self
, start_ts
):
116 for cpu
in self
.cpus
.keys():
117 current_cpu
= self
.cpus
[cpu
]
118 current_cpu
.cpu_ns
= 0
119 if current_cpu
.start_task_ns
!= 0:
120 current_cpu
.start_task_ns
= start_ts
121 if current_cpu
.current_tid
>= 0:
122 self
.tids
[current_cpu
.current_tid
].last_sched
= start_ts
123 for tid
in self
.tids
.keys():
124 self
.tids
[tid
].cpu_ns
= 0
125 self
.tids
[tid
].migrate_count
= 0
126 self
.tids
[tid
].read
= 0
127 self
.tids
[tid
].write
= 0
128 for syscall
in self
.tids
[tid
].syscalls
.keys():
129 self
.tids
[tid
].syscalls
[syscall
].count
= 0
131 if __name__
== "__main__":
132 parser
= argparse
.ArgumentParser(description
='CPU usage analysis')
133 parser
.add_argument('path', metavar
="<path/to/trace>", help='Trace path')
134 parser
.add_argument('-r', '--refresh', type=int,
135 help='Refresh period in seconds', default
=0)
136 parser
.add_argument('--top', type=int, default
=10,
137 help='Limit to top X TIDs (default = 10)')
138 args
= parser
.parse_args()
141 traces
= TraceCollection()
142 handle
= traces
.add_trace(args
.path
, "ctf")
150 traces
.remove_trace(handle
)
This page took 0.039149 seconds and 6 git commands to generate.