1 # The MIT License (MIT)
3 # Copyright (C) 2015 - Julien Desfossez <jdesfossez@efficios.com>
4 # 2015 - Antoine Busque <abusque@efficios.com>
5 # 2015 - Philippe Proulx <pproulx@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 from ..core
import memtop
27 from ..ascii_graph
import Pyasciigraph
32 class Memtop(Command
):
33 _DESC
= """The memtop command."""
34 _ANALYSIS_CLASS
= memtop
.Memtop
35 _MI_TITLE
= 'Top memory usage'
36 _MI_DESCRIPTION
= 'Per-TID top allocated/freed memory'
37 _MI_TAGS
= [mi
.Tags
.MEMORY
, mi
.Tags
.TOP
]
38 _MI_TABLE_CLASS_ALLOCD
= 'allocd'
39 _MI_TABLE_CLASS_FREED
= 'freed'
40 _MI_TABLE_CLASS_TOTAL
= 'total'
41 _MI_TABLE_CLASS_SUMMARY
= 'summary'
44 _MI_TABLE_CLASS_ALLOCD
,
45 'Per-TID top allocated memory', [
46 ('process', 'Process', mi
.Process
),
47 ('pages', 'Allocated pages', mi
.Integer
, 'pages'),
51 _MI_TABLE_CLASS_FREED
,
52 'Per-TID top freed memory', [
53 ('process', 'Process', mi
.Process
),
54 ('pages', 'Freed pages', mi
.Integer
, 'pages'),
58 _MI_TABLE_CLASS_TOTAL
,
59 'Total allocated/freed memory', [
60 ('allocd', 'Total allocated pages', mi
.Integer
, 'pages'),
61 ('freed', 'Total freed pages', mi
.Integer
, 'pages'),
65 _MI_TABLE_CLASS_SUMMARY
,
66 'Memory usage - summary', [
67 ('time_range', 'Time range', mi
.TimeRange
),
68 ('allocd', 'Total allocated pages', mi
.Integer
, 'pages'),
69 ('freed', 'Total freed pages', mi
.Integer
, 'pages'),
74 def _analysis_tick(self
, begin_ns
, end_ns
):
75 allocd_table
= self
._get
_per
_tid
_allocd
_result
_table
(begin_ns
, end_ns
)
76 freed_table
= self
._get
_per
_tid
_freed
_result
_table
(begin_ns
, end_ns
)
77 total_table
= self
._get
_total
_result
_table
(begin_ns
, end_ns
)
80 self
._mi
_append
_result
_table
(allocd_table
)
81 self
._mi
_append
_result
_table
(freed_table
)
82 self
._mi
_append
_result
_table
(total_table
)
84 self
._print
_date
(begin_ns
, end_ns
)
85 self
._print
_per
_tid
_allocd
(allocd_table
)
86 self
._print
_per
_tid
_freed
(freed_table
)
87 self
._print
_total
(total_table
)
89 def _create_summary_result_tables(self
):
90 total_tables
= self
._mi
_get
_result
_tables
(self
._MI
_TABLE
_CLASS
_TOTAL
)
91 begin
= total_tables
[0].timerange
.begin
92 end
= total_tables
[-1].timerange
.end
94 self
._mi
_create
_result
_table
(self
._MI
_TABLE
_CLASS
_SUMMARY
,
97 for total_table
in total_tables
:
98 total_allocd
= total_table
.rows
[0].allocd
99 total_freed
= total_table
.rows
[0].freed
100 summary_table
.append_row(
101 time_range
=total_table
.timerange
,
106 self
._mi
_clear
_result
_tables
()
107 self
._mi
_append
_result
_table
(summary_table
)
109 def _get_per_tid_attr_result_table(self
, table_class
, attr
,
111 result_table
= self
._mi
_create
_result
_table
(table_class
,
115 for tid
in sorted(self
._analysis
.tids
.values(),
116 key
=operator
.attrgetter(attr
),
118 if not self
._filter
_process
(tid
):
121 result_table
.append_row(
122 process
=mi
.Process(tid
.comm
, tid
=tid
.tid
),
123 pages
=mi
.Integer(getattr(tid
, attr
)),
127 if self
._args
.limit
> 0 and count
>= self
._args
.limit
:
132 def _get_per_tid_allocd_result_table(self
, begin_ns
, end_ns
):
133 return self
._get
_per
_tid
_attr
_result
_table
(self
._MI
_TABLE
_CLASS
_ALLOCD
,
137 def _get_per_tid_freed_result_table(self
, begin_ns
, end_ns
):
138 return self
._get
_per
_tid
_attr
_result
_table
(self
._MI
_TABLE
_CLASS
_FREED
,
142 def _get_total_result_table(self
, begin_ns
, end_ns
):
143 result_table
= self
._mi
_create
_result
_table
(self
._MI
_TABLE
_CLASS
_TOTAL
,
148 for tid
in self
._analysis
.tids
.values():
149 if not self
._filter
_process
(tid
):
152 alloc
+= tid
.allocated_pages
153 freed
+= tid
.freed_pages
155 result_table
.append_row(
156 allocd
=mi
.Integer(alloc
),
157 freed
=mi
.Integer(freed
),
162 def _print_per_tid_result(self
, result_table
, title
):
163 graph
= Pyasciigraph()
166 for row
in result_table
.rows
:
167 process_do
= row
.process
168 pages
= row
.pages
.value
169 values
.append(('%s (%d)' % (process_do
.name
, process_do
.tid
),
172 for line
in graph
.graph(title
, values
, unit
=' pages'):
175 def _print_per_tid_allocd(self
, result_table
):
176 self
._print
_per
_tid
_result
(result_table
, 'Per-TID Memory Allocations')
178 def _print_per_tid_freed(self
, result_table
):
179 self
._print
_per
_tid
_result
(result_table
,
180 'Per-TID Memory Deallocations')
182 def _print_total(self
, result_table
):
183 alloc
= result_table
.rows
[0].allocd
.value
184 freed
= result_table
.rows
[0].freed
.value
185 print('\nTotal memory usage:\n- %d pages allocated\n- %d pages freed' %
188 def _add_arguments(self
, ap
):
189 Command
._add
_proc
_filter
_args
(ap
)
190 Command
._add
_top
_args
(ap
)
194 memtopcmd
= Memtop(mi_mode
=mi_mode
)
198 # entry point (human)
This page took 0.035536 seconds and 5 git commands to generate.