Memstats

Memstats Git Source Tree

Root/memstats

1#!/usr/bin/perl
2
3#
4# memstats lists processes memory usage
5# Copyright 2014 Grégory Soutadé
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20
21use POSIX ();
22use Getopt::Long;
23
24# Convert int to kilobytes, megabytes and gigabytes
25sub printPacked {
26 my ($size) = @_;
27 my $suffix = "";
28
29 if($size < 1024*1024)
30 {
31$suffix = "k";
32$size = int($size/1024);
33 }
34 elsif($size < 1024*1024*1024)
35 {
36$suffix = "m";
37$size = int($size/(1024*1024));
38 }
39 else
40 {
41$suffix = "g";
42$size /= 1024*1024*1024;
43if ($size != int($size))
44{
45 $size = sprintf "%.2f", $size;
46}
47 }
48
49 return "$size$suffix";
50}
51
52# Convert seconds in hours:minutes:seconds
53sub printTime {
54 my ($time) = @_;
55 my $res = "";
56
57 $seconds = $time % 60;
58 $minutes = 0;
59 $hours = 0;
60 if ($time < 60)
61 {
62$seconds = $time;
63$minutes = 0;
64$hours = 0;
65 }
66 else
67 {
68$seconds = $time % 60;
69$time -= $seconds;
70$time /= 60;
71if ($time < 60)
72{
73 $minutes = $time;
74 $hours = 0;
75}
76else
77{
78 $minutes = $time % 60;
79 $time -= $minutes;
80 $time /= 60;
81 $hours = $time;
82}
83 }
84
85 $res = sprintf "%02d:%02d:%02d", $hours, $minute, $seconds;
86
87 return $res;
88}
89
90# PID OWNER USER VIRT RES S TIME COMMAND
91my @sizes ;
92my @lines ;
93
94# Put line to column writer
95sub putLine {
96 my ($line) = @_;
97
98 push @lines, $line;
99
100 @s = split(/ /, $line);
101 if (scalar(@sizes) == 0)
102 {
103foreach $v (@s) {push @sizes, length($v);}
104 }
105 else
106 {
107for($i=0; $i<scalar(@sizes); $i++)
108{
109 $l = length($s[$i]);
110 $sizes[$i] = $l if ($l > $sizes[$i]);
111}
112 }
113}
114
115# Compute column format
116sub computeFormat {
117 my $format = "";
118
119 for($i=0; $i<scalar(@sizes); $i++)
120 {
121if ($i > 0)
122{
123 $format .= sprintf " %%%ds", $sizes[$i];
124}
125else
126{
127 $format .= sprintf "%%%ds", $sizes[$i];
128}
129 }
130 $format .= "\n";
131
132 return $format;
133}
134
135# Get current start time in seconds
136sub getStartTime {
137 open(FIC,"</proc/self/stat") or die $!;
138 my @infos = split(/ /, <FIC>);
139 close (FIC);
140
141 return $infos[21];
142}
143
144# Constants
145my $clock_ticks = POSIX::sysconf(&POSIX::_SC_CLK_TCK );
146my $page_size = POSIX::sysconf(&POSIX::_SC_PAGESIZE);
147my $starttime = getStartTime();
148my $NB_PROCESSES = 30;
149my $help;
150my $all;
151my $virt;
152
153# Process paramters
154my $program_name = $0;
155
156GetOptions ("nb_processes=i" => \$NB_PROCESSES,
157 "all" => \$all,
158 "virt" => \$virt,
159 "help" => \$help);
160
161if ($help)
162{
163 printf "Display processes memory usage\nusage: %s [--all|--nb_processes=NB_PROCESSES] [--virt]\n", $program_name;
164 print "\t--all:\t\tList all processes\n";
165 print "\t--nb_processes:\tLimit list to NB_PROCESSES (default: 30)\n";
166 print "\t--virt:\t\tSort by virtual memory (RES by default)\n";
167
168 exit(0);
169}
170
171$NB_PROCESSES = -1 if ($all);
172
173############ START ############
174
175my @processes;
176
177# Analyze all processes
178opendir (DIR, "/proc") or die $!;
179
180while (my $pid = readdir(DIR)) {
181 next if ($pid !~ /[0-9]+/);
182
183 # Get owner name
184 my $uid = 0;
185 open(FIC,"</proc/$pid/status") or die $!;
186 while( defined( $l = <FIC> ) ) {
187if ($l =~ /Uid:\s+([0-9]+)\s+.*/)
188{
189 $uid = $1;
190 last;
191}
192 }
193 close (FIC);
194
195 ($owner_name,$passwd,$uid,$gid,
196 $quota,$comment,$gcos,$dir,$shell,$expire) = getpwuid($uid);
197
198 # Get infos
199 open(FIC,"</proc/$pid/stat") or die $!;
200 my @infos = split(/ /, <FIC>);
201 close (FIC);
202
203 push @processes,
204 {"pid" => $infos[0],
205 "owner" => $owner_name,
206 "comm" => $infos[1],
207 "state" => $infos[2],
208 "starttime" => $infos[21],
209 "vsize" => $infos[22],
210 "rss" => $infos[23],
211 };
212}
213
214# Sort in reverse order by memory usage
215if ($virt)
216{
217 @p = sort {$b->{vsize} <=> $a->{vsize}} @processes;
218}
219else
220{
221 @p = sort {$b->{rss} <=> $a->{rss}} @processes;
222}
223
224# Compute lines
225putLine("PID OWNER VIRT RES S TIME COMMAND");
226
227foreach $e (@p)
228{
229 $vsize = printPacked($$e{vsize});
230 $rss = printPacked($$e{rss}*$page_size);
231 $time = int(($starttime-$$e{starttime}) / $clock_ticks);
232 $time = printTime $time;
233 $name = $$e{comm};
234 $name =~ s/\(//;
235 $name =~ s/\)//;
236
237 last if ($NB_PROCESSES > 0 && scalar(@lines) > $NB_PROCESSES);
238
239 putLine("$$e{pid} $$e{owner} $vsize $rss $$e{state} $time $name");
240}
241
242my $format = computeFormat;
243
244# Start display
245foreach $l (@lines)
246{
247 printf $format, split(/ /, $l);
248}

Archive Download this file

Branches