The Gaudi Framework  master (da3d77e1)
ProcStats.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 // Class: ProcStats
12 // Purpose: To keep statistics on memory use
13 // Warning: Only Linux implementation at the present time...
14 #ifdef __ICC
15 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
16 // meant
17 # pragma warning( disable : 2259 )
18 #endif
19 
20 #include "ProcStats.h"
21 #include <memory>
22 
23 #if defined( __linux__ ) or defined( __APPLE__ )
24 # include <iostream>
25 # include <sstream>
26 # include <sys/signal.h>
27 # include <sys/syscall.h>
28 # ifdef __linux__
29 # include <sys/procfs.h>
30 # endif // __linux__
31 # include <cstdio>
32 
33 /* Format of the Linux proc/stat (man 5 proc, kernel 2.6.35):
34  pid %d The process ID.
35 
36  comm %s The filename of the executable, in parentheses. This is visible
37  whether or not the executable is swapped out.
38 
39  state %c One character from the string "RSDZTW" where R is running, S is
40  sleeping in an interruptible wait, D is waiting in uninterruptible
41  disk sleep, Z is zombie, T is traced or stopped (on a signal), and
42  W is paging.
43 
44  ppid %d The PID of the parent.
45 
46  pgrp %d The process group ID of the process.
47 
48  session %d The session ID of the process.
49 
50  tty_nr %d The controlling terminal of the process. (The minor device number
51  is contained in the combination of bits 31 to 20 and 7 to 0; the
52  major device number is in bits 15 t0 8.)
53 
54  tpgid %d The ID of the foreground process group of the controlling terminal
55  of the process.
56 
57  flags %u (%lu before Linux 2.6.22)
58  The kernel flags word of the process. For bit meanings, see the
59  PF_* defines in <linux/sched.h>. Details depend on the kernel
60  version.
61 
62  minflt %lu The number of minor faults the process has made which have not
63  required loading a memory page from disk.
64 
65  cminflt %lu The number of minor faults that the process's waited-for children
66  have made.
67 
68  majflt %lu The number of major faults the process has made which have
69  required loading a memory page from disk.
70 
71  cmajflt %lu The number of major faults that the process's waited-for children
72  have made.
73 
74  utime %lu Amount of time that this process has been scheduled in user mode,
75  measured in clock ticks (divide by sysconf(_SC_CLK_TCK). This
76  includes guest time, guest_time (time spent running a virtual CPU,
77  see below), so that applications that are not aware of the guest
78  time field do not lose that time from their calculations.
79 
80  stime %lu Amount of time that this process has been scheduled in kernel
81  mode, measured in clock ticks (divide by sysconf(_SC_CLK_TCK).
82 
83  cutime %ld Amount of time that this process's waited-for children have been
84  scheduled in user mode, measured in clock ticks (divide by
85  sysconf(_SC_CLK_TCK). (See also times(2).) This includes guest
86  time, cguest_time (time spent running a virtual CPU, see below).
87 
88  cstime %ld Amount of time that this process's waited-for children have been
89  scheduled in kernel mode, measured in clock ticks (divide by
90  sysconf(_SC_CLK_TCK).
91 
92  priority %ld
93  (Explanation for Linux 2.6) For processes running a real-time
94  scheduling policy (policy below; see sched_setscheduler(2)), this
95  is the negated scheduling priority, minus one; that is, a number
96  in the range -2 to -100, corresponding to real-time priorities 1
97  to 99. For processes running under a non-real-time scheduling
98  policy, this is the raw nice value (setpriority(2)) as represented
99  in the kernel. The kernel stores nice values as numbers in the
100  range 0 (high) to 39 (low), corresponding to the user-visible nice
101  range of -20 to 19.
102 
103  Before Linux 2.6, this was a scaled value based on the scheduler
104  weighting given to this process.
105 
106  nice %ld The nice value (see setpriority(2)), a value in the range 19 (low
107  priority) to -20 (high priority).
108 
109  num_threads %ld
110  Number of threads in this process (since Linux 2.6). Before ker‐
111  nel 2.6, this field was hard coded to 0 as a placeholder for an
112  earlier removed field.
113 
114  itrealvalue %ld
115  The time in jiffies before the next SIGALRM is sent to the process
116  due to an interval timer. Since kernel 2.6.17, this field is no
117  longer maintained, and is hard coded as 0.
118 
119  starttime %llu (was %lu before Linux 2.6)
120  The time in jiffies the process started after system boot.
121 
122  vsize %lu Virtual memory size in bytes.
123 
124  rss %ld Resident Set Size: number of pages the process has in real memory.
125  This is just the pages which count towards text, data, or stack
126  space. This does not include pages which have not been demand-
127  loaded in, or which are swapped out.
128 
129  rsslim %lu Current soft limit in bytes on the rss of the process; see the
130  description of RLIMIT_RSS in getpriority(2).
131 
132  startcode %lu
133  The address above which program text can run.
134 
135  endcode %lu The address below which program text can run.
136 
137  startstack %lu
138  The address of the start (i.e., bottom) of the stack.
139 
140  kstkesp %lu The current value of ESP (stack pointer), as found in the kernel
141  stack page for the process.
142 
143  kstkeip %lu The current EIP (instruction pointer).
144 
145  signal %lu The bitmap of pending signals, displayed as a decimal number.
146  Obsolete, because it does not provide information on real-time
147  signals; use /proc/[pid]/status instead.
148 
149  blocked %lu The bitmap of blocked signals, displayed as a decimal number.
150  Obsolete, because it does not provide information on real-time
151  signals; use /proc/[pid]/status instead.
152 
153  sigignore %lu
154  The bitmap of ignored signals, displayed as a decimal number.
155  Obsolete, because it does not provide information on real-time
156  signals; use /proc/[pid]/status instead.
157 
158  sigcatch %lu
159  The bitmap of caught signals, displayed as a decimal number.
160  Obsolete, because it does not provide information on real-time
161  signals; use /proc/[pid]/status instead.
162 
163  wchan %lu This is the "channel" in which the process is waiting. It is the
164  address of a system call, and can be looked up in a namelist if
165  you need a textual name. (If you have an up-to-date
166  /etc/psdatabase, then try ps -l to see the WCHAN field in action.)
167 
168  nswap %lu Number of pages swapped (not maintained).
169 
170  cnswap %lu Cumulative nswap for child processes (not maintained).
171 
172  exit_signal %d (since Linux 2.1.22)
173  Signal to be sent to parent when we die.
174 
175  processor %d (since Linux 2.2.8)
176  CPU number last executed on.
177 
178  rt_priority %u (since Linux 2.5.19; was %lu before Linux 2.6.22)
179  Real-time scheduling priority, a number in the range 1 to 99 for
180  processes scheduled under a real-time policy, or 0, for non-real-
181  time processes (see sched_setscheduler(2)).
182 
183  policy %u (since Linux 2.5.19; was %lu before Linux 2.6.22)
184  Scheduling policy (see sched_setscheduler(2)). Decode using the
185  SCHED_* constants in linux/sched.h.
186 
187  delayacct_blkio_ticks %llu (since Linux 2.6.18)
188  Aggregated block I/O delays, measured in clock ticks (centisec‐
189  onds).
190 
191  guest_time %lu (since Linux 2.6.24)
192  Guest time of the process (time spent running a virtual CPU for a
193  guest operating system), measured in clock ticks (divide by
194  sysconf(_SC_CLK_TCK).
195 
196  cguest_time %ld (since Linux 2.6.24)
197  Guest time of the process's children, measured in clock ticks
198  (divide by sysconf(_SC_CLK_TCK).
199 */
200 struct linux_proc {
201  int pid{ -1 };
202  char comm[400];
203  char state;
204  int ppid{ -1 };
205  int pgrp{ -1 };
206  int session{ -1 };
207  int tty{ -1 };
208  int tpgid{ -1 };
209  unsigned long flags{ 0 };
210  unsigned long minflt{ 0 };
211  unsigned long cminflt{ 0 };
212  unsigned long majflt{ 0 };
213  unsigned long cmajflt{ 0 };
214  unsigned long utime{ 0 };
215  unsigned long stime{ 0 };
216  long cutime{ 0 };
217  long cstime{ 0 };
218  long priority{ 0 };
219  long nice{ 0 };
220  long num_threads{ 0 };
221  long itrealvalue{ 0 };
222  unsigned long long starttime{ 0 };
223  unsigned long vsize{ 0 };
224  long rss{ 0 };
225  unsigned long rlim{ 0 };
226  unsigned long startcode{ 0 };
227  unsigned long endcode{ 0 };
228  unsigned long startstack{ 0 };
229  unsigned long kstkesp{ 0 };
230  unsigned long kstkeip{ 0 };
231  unsigned long signal{ 0 };
232  unsigned long blocked{ 0 };
233  unsigned long sigignore{ 0 };
234  unsigned long sigcatch{ 0 };
235  unsigned long wchan{ 0 };
236 };
237 #endif // __linux__ or __APPLE__
238 
240  static ProcStats inst{};
241  return &inst;
242 }
243 
245  m_valid = false;
246 #if defined( __linux__ ) or defined( __APPLE__ )
247  m_ufd.close();
248  m_pg_size = sysconf( _SC_PAGESIZE ); // getpagesize();
249  const auto fname = "/proc/" + std::to_string( getpid() ) + "/stat";
250  m_ufd.open( fname.c_str(), O_RDONLY );
251  if ( !m_ufd ) {
252  std::cerr << "ProcStats : Failed to open " << fname << std::endl;
253  } else {
254  m_valid = true;
255  }
256 #endif // __linux__ or __APPLE__
257 }
258 
260  if ( !m_valid ) { return false; }
261 
262  std::scoped_lock lock{ m_mutex };
263 
264 #if defined( __linux__ ) or defined( __APPLE__ )
265 
266  auto read_proc = [&]() {
267  bool ok = true;
268  int cnt{ 0 };
269  char buf[500];
270  linux_proc pinfo;
271  m_ufd.lseek( 0, SEEK_SET );
272  if ( ( cnt = m_ufd.read( buf, sizeof( buf ) ) ) < 0 ) { ok = false; }
273  if ( cnt > 0 ) {
274  buf[std::min( static_cast<std::size_t>( cnt ), sizeof( buf ) - 1 )] = '\0';
275  sscanf(
276  buf,
277  // 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9
278  // 30 1 2 3 4 5
279  "%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %llu %lu %ld %lu %lu %lu %lu "
280  "%lu %lu %lu %lu %lu %lu %lu",
281  &pinfo.pid, pinfo.comm, &pinfo.state, &pinfo.ppid, &pinfo.pgrp, &pinfo.session, &pinfo.tty, &pinfo.tpgid,
282  &pinfo.flags, &pinfo.minflt, &pinfo.cminflt, &pinfo.majflt, &pinfo.cmajflt, &pinfo.utime, &pinfo.stime,
283  &pinfo.cutime, &pinfo.cstime, &pinfo.priority, &pinfo.nice, &pinfo.num_threads, &pinfo.itrealvalue,
284  &pinfo.starttime, &pinfo.vsize, &pinfo.rss, &pinfo.rlim, &pinfo.startcode, &pinfo.endcode, &pinfo.startstack,
285  &pinfo.kstkesp, &pinfo.kstkeip, &pinfo.signal, &pinfo.blocked, &pinfo.sigignore, &pinfo.sigcatch,
286  &pinfo.wchan );
287  // resident set size in pages
288  const auto pr_size = static_cast<double>( pinfo.vsize );
289  const auto pr_rssize = static_cast<double>( pinfo.rss );
290  constexpr double MB = 1.0 / ( 1024 * 1024 );
291  f.vsize = pr_size * MB;
292  f.rss = pr_rssize * m_pg_size * MB;
293  if ( 0 == pinfo.vsize ) { ok = false; }
294  }
295  return ok;
296  };
297 
298  // attempt to read from proc
299  if ( !read_proc() ) {
300  std::cerr << "ProcStats : -> Problems reading proc file. Will try reopening..." << std::endl;
301  open_ufd();
302  if ( !read_proc() ) { return false; }
303  }
304 
305 #else
306  f.vsize = 0;
307  f.rss = 0;
308  return false;
309 #endif // __linux__ or __APPLE__
310 
311  m_curr.rss = f.rss;
312  m_curr.vsize = f.vsize;
313 
314  return true;
315 }
linux_proc::blocked
unsigned long blocked
Definition: ProcessDescriptor.cpp:299
linux_proc::vsize
unsigned long vsize
Definition: ProcessDescriptor.cpp:290
linux_proc::rss
long rss
Definition: ProcessDescriptor.cpp:291
linux_proc::endcode
unsigned long endcode
Definition: ProcessDescriptor.cpp:294
linux_proc::comm
char comm[400]
Definition: ProcessDescriptor.cpp:269
linux_proc::starttime
unsigned long long starttime
Definition: ProcessDescriptor.cpp:289
linux_proc::tty
int tty
Definition: ProcessDescriptor.cpp:274
linux_proc::startcode
unsigned long startcode
Definition: ProcessDescriptor.cpp:293
linux_proc::itrealvalue
long itrealvalue
Definition: ProcessDescriptor.cpp:288
procInfo
Definition: ProcStats.h:29
linux_proc::wchan
unsigned long wchan
Definition: ProcessDescriptor.cpp:302
ProcStats::instance
static ProcStats * instance()
Definition: ProcStats.cpp:239
linux_proc::ppid
int ppid
Definition: ProcessDescriptor.cpp:271
ProcStats
Definition: ProcStats.h:38
linux_proc::tpgid
int tpgid
Definition: ProcessDescriptor.cpp:275
linux_proc::priority
long priority
Definition: ProcessDescriptor.cpp:285
procInfo::vsize
double vsize
Definition: ProcStats.h:34
linux_proc::majflt
unsigned long majflt
Definition: ProcessDescriptor.cpp:279
linux_proc::flags
unsigned long flags
Definition: ProcessDescriptor.cpp:276
linux_proc::stime
unsigned long stime
Definition: ProcessDescriptor.cpp:282
linux_proc::num_threads
long num_threads
Definition: ProcessDescriptor.cpp:287
GaudiMP.GMPBase.MB
MB
Definition: GMPBase.py:61
linux_proc::rlim
unsigned long rlim
Definition: ProcessDescriptor.cpp:292
std::cerr
ProcStats::m_pg_size
double m_pg_size
Definition: ProcStats.h:105
linux_proc::startstack
unsigned long startstack
Definition: ProcessDescriptor.cpp:295
linux_proc
Definition: ProcessDescriptor.cpp:267
ProcStats::unique_fd::open
unique_fd & open(Args &&... args)
Definition: ProcStats.h:72
std::to_string
T to_string(T... args)
ProcStats::unique_fd::close
int close()
Definition: ProcStats.h:76
ProcStats::m_mutex
std::mutex m_mutex
Definition: ProcStats.h:108
linux_proc::cminflt
unsigned long cminflt
Definition: ProcessDescriptor.cpp:278
ProcStats.h
ProcStats::m_curr
procInfo m_curr
Definition: ProcStats.h:106
linux_proc::signal
unsigned long signal
Definition: ProcessDescriptor.cpp:298
linux_proc::minflt
unsigned long minflt
Definition: ProcessDescriptor.cpp:277
linux_proc::pgrp
int pgrp
Definition: ProcessDescriptor.cpp:272
linux_proc::kstkesp
unsigned long kstkesp
Definition: ProcessDescriptor.cpp:296
linux_proc::sigcatch
unsigned long sigcatch
Definition: ProcessDescriptor.cpp:301
linux_proc::pid
int pid
Definition: ProcessDescriptor.cpp:268
std::min
T min(T... args)
ProcStats::m_ufd
unique_fd m_ufd
Definition: ProcStats.h:104
std::endl
T endl(T... args)
linux_proc::state
char state
Definition: ProcessDescriptor.cpp:270
ProcStats::open_ufd
void open_ufd()
Definition: ProcStats.cpp:244
ProcStats::fetch
bool fetch(procInfo &fill_me)
Definition: ProcStats.cpp:259
linux_proc::sigignore
unsigned long sigignore
Definition: ProcessDescriptor.cpp:300
linux_proc::session
int session
Definition: ProcessDescriptor.cpp:273
procInfo::rss
double rss
Definition: ProcStats.h:35
std::size_t
ProcStats::m_valid
bool m_valid
Definition: ProcStats.h:107
linux_proc::cmajflt
unsigned long cmajflt
Definition: ProcessDescriptor.cpp:280
linux_proc::kstkeip
unsigned long kstkeip
Definition: ProcessDescriptor.cpp:297
linux_proc::utime
unsigned long utime
Definition: ProcessDescriptor.cpp:281
linux_proc::nice
long nice
Definition: ProcessDescriptor.cpp:286
linux_proc::cstime
long cstime
Definition: ProcessDescriptor.cpp:284
linux_proc::cutime
long cutime
Definition: ProcessDescriptor.cpp:283