DABC (Data Acquisition Backbone Core)  2.9.9
statistic.cxx
Go to the documentation of this file.
1 // $Id: statistic.cxx 4747 2021-03-23 14:49:44Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #include "dabc/statistic.h"
17 
18 #include <cmath>
19 #include <cstring>
20 #include <unistd.h>
21 
22 #include "dabc/logging.h"
23 #include "dabc/timing.h"
24 
26  fStatFp(0),
27  fProcStatFp(0),
28  fCPUs(),
29  fVmSize(0),
30  fVmPeak(0),
31  fNumThreads(0)
32 {
33  const char* cpu_stat_file = "/proc/stat";
34 
35  fStatFp = fopen (cpu_stat_file, "r");
36  if (fStatFp==0)
37  EOUT("fopen of %s failed", cpu_stat_file);
38 
39 
40  if (withmem) {
41  pid_t id = getpid();
42 
43  char fname[100];
44  snprintf(fname, sizeof(fname), "/proc/%d/status", id);
45 
46  fProcStatFp = fopen(fname,"r");
47  if (fProcStatFp==0)
48  EOUT("fopen of %s failed", fname);
49  }
50 
51  Measure();
52 }
53 
55 {
56  if (fStatFp!=0)
57  if (fclose (fStatFp) != 0)
58  EOUT("fclose of stat file failed");
59 
60  if (fProcStatFp!=0)
61  if (fclose (fProcStatFp) != 0)
62  EOUT("fclose of proc stat file failed");
63 }
64 
66 {
67  if (fStatFp==0) return false;
68 
69  rewind(fStatFp);
70 
71  fflush(fStatFp);
72 
73  char buffer[1024];
74 
75  unsigned cnt = 0;
76 
77  while (fgets(buffer, sizeof(buffer), fStatFp)) {
78 
79  if (strncmp (buffer, "cpu", 3)!=0) break;
80 
81  const char* info = buffer;
82 
83  while ((*info!=' ') && (*info != 0)) info++;
84  if (*info==0) break;
85 
86  unsigned long curr_user(0), curr_nice(0), curr_sys(0), curr_idle(0);
87 
88  sscanf(info, "%lu %lu %lu %lu", &curr_user, &curr_nice, &curr_sys, &curr_idle);
89 
90  //DOUT0("Scan:%s", info));
91  //if (cnt==0)
92  // DOUT0("Res:%lu %lu %lu %lu", curr_user, curr_nice, curr_sys, curr_idle);
93 
94  curr_user += curr_nice;
95 
96  unsigned long user(0), sys(0), idle(0);
97 
98  if (cnt>=fCPUs.size()) {
99  fCPUs.push_back(SingleCpu());
100  } else {
101  user = curr_user - fCPUs[cnt].last_user;
102  sys = curr_sys - fCPUs[cnt].last_sys;
103  idle = curr_idle - fCPUs[cnt].last_idle;
104  }
105 
106  unsigned long total = user + sys + idle;
107  if (total>0) {
108  fCPUs[cnt].user_util = 1. * user / total;
109  fCPUs[cnt].sys_util = 1. * sys / total;
110  fCPUs[cnt].cpu_util = 1. * (user + sys) / total;
111  } else {
112  fCPUs[cnt].user_util = 0.;
113  fCPUs[cnt].sys_util = 0.;
114  fCPUs[cnt].cpu_util = 0.;
115  }
116 
117  fCPUs[cnt].last_user = curr_user;
118  fCPUs[cnt].last_sys = curr_sys;
119  fCPUs[cnt].last_idle = curr_idle;
120 
121  cnt++;
122  }
123 
124  if (fProcStatFp != 0) {
125  rewind(fProcStatFp);
126  fflush(fProcStatFp);
127 
128  while (fgets(buffer, sizeof(buffer), fProcStatFp)) {
129  if (strncmp(buffer, "VmSize:", 7)==0)
130  sscanf(buffer + 7, "%lu", &fVmSize);
131  else
132  if (strncmp(buffer, "VmPeak:", 7)==0)
133  sscanf(buffer + 7, "%lu", &fVmPeak);
134  else
135  if (strncmp(buffer, "Threads:", 8)==0) {
136  sscanf(buffer + 8, "%lu", &fNumThreads);
137  break;
138  }
139  }
140  }
141 
142  return true;
143 }
144 
146 {
147  fCPUs.clear();
148  return Measure();
149 }
150 
152 {
153  pid_t id = getpid();
154 
155  char fname[100];
156  snprintf(fname, sizeof(fname), "/proc/%d/status", id);
157 
158  FILE* f = fopen(fname,"r");
159  if (f==0) return 0;
160  char buf[256];
161 
162  long sz = 0;
163 
164  while(fgets(buf, sizeof(buf), f)) {
165  int rc = sscanf(buf, "VmSize: %ld", &sz);
166  if (rc == 1) break;
167  }
168  fclose(f);
169 
170  return sz;
171 }
172 
173 // ____________________________________________________________________________
174 
175 
176 
178 {
179  fMeasureInterval = 0;
180  fMeasurePoints = 0;
181  fPoints = 0;
182  Reset();
183 }
184 
186 {
187  Reset();
188 }
189 
190 void dabc::Ratemeter::Packet(int size, double now)
191 {
192  if (now <= 0.) now = dabc::Now().AsDouble();
193 
194  if (firstoper<=0.) {
195  firstoper = now;
196  lastoper = 0.;
197  numoper = 0;
198  totalpacketsize = 0;
199  } else
200  if (now>=firstoper) {
201  lastoper = now;
202  numoper++;
203  totalpacketsize+=size;
204  } else
205  return; // do not account packets comming before expected start of measurement
206 
207  if ((fPoints!=0) && (fMeasureInterval>0)) {
208  long npnt = lrint((now - firstoper) / fMeasureInterval);
209  if ((npnt>=0) && (npnt<fMeasurePoints))
210  fPoints[npnt] += size / fMeasureInterval;
211  }
212 }
213 
215 {
216  firstoper = 0.;
217  lastoper = 0.;
218  numoper = 0;
219  totalpacketsize = 0;
220 
221  if (fPoints) {
222  delete[] fPoints;
223  fPoints = nullptr;
224  fMeasureInterval = 0;
225  fMeasurePoints = 0;
226  }
227 }
228 
230 {
231  // calculate rate as MB/s
232 
233  double totaltm = GetTotalTime();
234  if ((numoper<2) || (totaltm<=0.)) return 0.;
235  return totalpacketsize / totaltm * 1e-6;
236 }
237 
239 {
240  return lastoper - firstoper;
241 }
242 
244 {
245  if (numoper<=0) return 0;
246  return totalpacketsize/numoper;
247 }
248 
249 void dabc::Ratemeter::DoMeasure(double interval_sec, long npoints, double firsttm)
250 {
251  Reset();
252  fMeasureInterval = interval_sec;
253  fMeasurePoints = npoints;
254  fPoints = new double[fMeasurePoints];
255  for (int n=0;n<fMeasurePoints;n++)
256  fPoints[n] = 0.;
257 
258  firstoper = firsttm;
259 }
260 
261 void dabc::Ratemeter::SaveRatesInFile(const char* fname, Ratemeter** rates, int nrates, bool withsum)
262 {
263  if (nrates<=0) return;
264 
265  int npoints = 0;
266  double interval = 0;
267  for (int nr=0;nr<nrates;nr++)
268  if (rates[nr]!=0) {
269  npoints = rates[nr]->fMeasurePoints;
270  interval = rates[nr]->fMeasureInterval;
271  }
272 
273  if ((npoints<=0) || (interval<=0)) return;
274 
275  FILE* f = fopen(fname,"w");
276  if (!f) return;
277 
278  for (int n=0;n<npoints;n++) {
279  fprintf(f, "%7.1f", n*interval*1e3); // time in millisec
280  double sum = 0.;
281  for (int nr=0;nr<nrates;nr++) {
282  if (rates[nr]==0) continue;
283  fprintf(f,"\t%5.1f", rates[nr]->fPoints[n]);
284  sum+=rates[nr]->fPoints[n];
285  }
286  if (withsum) fprintf(f,"\t%5.1f\n", sum);
287  else fprintf(f,"\n");
288  }
289 
290  fclose(f);
291 }
292 
293 void dabc::Ratemeter::SaveInFile(const char* fname)
294 {
295  Ratemeter* rate = this;
296  SaveRatesInFile(fname, &rate, 1, false);
297 }
298 
299 // ************************************************
300 
302 {
303  hist = 0;
304  nhist = 0;
305  hist_min = 0.;
306  hist_max = 1.;
307  Reset();
308 }
309 
310 
312 {
313  AllocateHist(0, 0., 1.);
314 }
315 
316 void dabc::Average::AllocateHist(int nbins, double xmin, double xmax)
317 {
318  if (hist) { delete[] hist; hist = 0; nhist = 0; }
319 
320  if ((nbins>0) && (xmax>xmin)) {
321  hist = new long[nbins+2];
322  nhist = nbins;
323  hist_min = xmin;
324  hist_max = xmax;
325  for (int n=0;n<nhist+2;n++) hist[n] = 0;
326  }
327 }
328 
329 
331 {
332  num = 0;
333  sum1=0.;
334  sum2=0.;
335  min=0.;
336  max=0.;
337  if (hist && nhist)
338  for (int n=0;n<nhist+2;n++)
339  hist[n] = 0;
340 }
341 
342 
343 void dabc::Average::Fill(double zn)
344 {
345  if (num==0) {
346  min = zn;
347  max = zn;
348  } else {
349  if (zn>max) max = zn; else
350  if (zn<min) min = zn;
351  }
352 
353  num++;
354  sum1 += zn;
355  sum2+= zn*zn;
356 
357  if (hist && nhist) {
358  if (zn<hist_min) hist[0]++; else
359  if (zn>=hist_max) hist[nhist+1]++; else {
360  // +0.5 to set integer value in the middle of interval
361  long bin = lrint((zn - hist_min) / (hist_max-hist_min) * nhist + 0.5);
362  if ((bin>0) && (bin<=nhist)) hist[bin]++;
363  else EOUT("Bin error bin = %ld nhist = %d", bin, nhist);
364  }
365  }
366 }
367 
368 double dabc::Average::Dev() const
369 {
370  if (num<=1) return 0.;
371  return sqrt(sum2/num - Mean()*Mean());
372 }
373 
374 void dabc::Average::Show(const char* name, bool showextr)
375 {
376  if (showextr)
377  DOUT0("%s = %f +- %f (min = %f, max = %f)",name,Mean(), Dev(), min, max);
378  else
379  DOUT0("%s = %f +- %f",name,Mean(), Dev());
380 }
381 
383 {
384  if ((hist==0) || (nhist==0)) return;
385 
386  long sum0(0);
387  for (int n=0;n<nhist+2;n++) sum0+=hist[n];
388  if (sum0<=0) sum0=1;
389 
390  DOUT1("Below %5.2f cnt = %3ld %5.1f", hist_min, hist[0], 100.*hist[0]/sum0);
391  long sum1 = hist[0];
392  for (int n=1;n<=nhist;n++) {
393  sum1+=hist[n];
394  DOUT1("Bin%02d x:%5.2f = %3ld %5.1f", n, (n - 0.5) / nhist * (hist_max-hist_min) + hist_min, hist[n], 100.*sum1/sum0);
395  }
396  DOUT1("Over %5.2f cnt = %3ld", hist_max, hist[nhist+1]);
397 }
virtual ~Average()
Definition: statistic.cxx:311
void ShowHist()
Definition: statistic.cxx:382
double Dev() const
Definition: statistic.cxx:368
void Show(const char *name, bool showextr=false)
Definition: statistic.cxx:374
void Fill(double zn)
Definition: statistic.cxx:343
void AllocateHist(int nbins, double xmin, double xmax)
Definition: statistic.cxx:316
virtual ~CpuStatistic()
Definition: statistic.cxx:54
CpuStatistic(bool withmem=false)
Definition: statistic.cxx:25
static long GetProcVirtMem()
Definition: statistic.cxx:151
FILE * fProcStatFp
Definition: statistic.h:42
Helper class to calculate data rate.
Definition: statistic.h:79
static void SaveRatesInFile(const char *fname, Ratemeter **rates, int nrates, bool withsum=false)
Definition: statistic.cxx:261
int AverPacketSize()
Definition: statistic.cxx:243
virtual ~Ratemeter()
Definition: statistic.cxx:185
double fMeasureInterval
Definition: statistic.h:103
void SaveInFile(const char *fname)
Definition: statistic.cxx:293
void DoMeasure(double interval_sec, long npoints, double firsttm=0.)
Definition: statistic.cxx:249
double GetTotalTime()
Definition: statistic.cxx:238
long fMeasurePoints
Definition: statistic.h:104
double GetRate()
Definition: statistic.cxx:229
void Packet(int size, double tm=0.)
Definition: statistic.cxx:190
double * fPoints
Definition: statistic.h:105
#define DOUT0(args ...)
Definition: logging.h:156
#define EOUT(args ...)
Definition: logging.h:150
#define DOUT1(args ...)
Definition: logging.h:162
TimeStamp Now()
Definition: timing.h:260
Definition: Factory.h:20
double AsDouble() const
Return time stamp in form of double (in seconds)
Definition: timing.h:120