MythTV  master
jitterometer.cpp
Go to the documentation of this file.
1 #include <sys/time.h>
2 #include <cstdlib>
3 #include <cmath>
4 
5 #include "mythlogging.h"
6 #include "jitterometer.h"
7 
8 #define UNIX_PROC_STAT "/proc/stat"
9 #define MAX_CORES 8
10 
11 Jitterometer::Jitterometer(const QString &nname, int ncycles)
12  : m_num_cycles(ncycles), m_name(nname)
13 {
14  m_times.resize(m_num_cycles);
15 
16  if (m_name.isEmpty())
17  m_name = "Jitterometer";
18 
19 #ifdef __linux__
20  if (QFile::exists(UNIX_PROC_STAT))
21  {
22  m_cpustat = new QFile(UNIX_PROC_STAT);
23  if (m_cpustat)
24  {
25  if (!m_cpustat->open(QIODevice::ReadOnly))
26  {
27  delete m_cpustat;
28  m_cpustat = nullptr;
29  }
30  else
31  {
32  m_laststats = new unsigned long long[MAX_CORES * 9];
33  memset(m_laststats, 0, sizeof(unsigned long long) * MAX_CORES * 9);
34  }
35  }
36  }
37 #endif
38 }
39 
41 {
42  if (m_cpustat)
43  m_cpustat->close();
44  delete m_cpustat;
45  delete [] m_laststats;
46 }
47 
49 {
50  m_num_cycles = cycles;
51  m_times.resize(m_num_cycles);
52  m_count = 0;
53 }
54 
56 {
57  if (!m_num_cycles)
58  return false;
59  bool ret = RecordEndTime();
61  return ret;
62 }
63 
65 {
66  if (!m_num_cycles)
67  return false;
68 
69  int cycles = m_num_cycles;
70  struct timeval timenow {};
71  gettimeofday(&timenow, nullptr);
72 
74  {
75  m_times[m_count] = (timenow.tv_sec - m_starttime.tv_sec ) * 1000000 +
76  (timenow.tv_usec - m_starttime.tv_usec) ;
77  m_count++;
78  }
79 
80  m_starttime_valid = false;
81 
82  if (m_count >= cycles)
83  {
84  /* compute and display stuff, reset count to -1 */
85  double mean = 0, sum_of_squared_deviations=0;
86  double standard_deviation;
87  double tottime = 0;
88  int i;
89 
90  /* compute the mean */
91  for(i = 0; i < cycles; i++)
92  mean += m_times[i];
93 
94  tottime = mean;
95  mean /= cycles;
96 
97  if (tottime > 0)
98  m_last_fps = cycles / tottime * 1000000;
99 
100  /* compute the sum of the squares of each deviation from the mean */
101  for(i = 0; i < cycles; i++)
102  sum_of_squared_deviations += (mean - m_times[i]) * (mean - m_times[i]);
103 
104  /* compute standard deviation */
105  standard_deviation = sqrt(sum_of_squared_deviations / (cycles - 1));
106  if (mean > 0)
107  m_last_sd = standard_deviation / mean;
108 
109  /* retrieve load if available */
110  QString extra;
112  if (!m_lastcpustats.isEmpty())
113  extra = QString("CPUs: ") + m_lastcpustats;
114 
115  LOG(VB_GENERAL, LOG_INFO,
116  m_name + QString("FPS: %1 Mean: %2 Std.Dev: %3 ")
117  .arg(m_last_fps, 7, 'f', 2).arg((int)mean, 5)
118  .arg((int)standard_deviation, 5) + extra);
119 
120  m_count = 0;
121  return true;
122  }
123  return false;
124 }
125 
127 {
128  if (!m_num_cycles)
129  return;
130  gettimeofday(&m_starttime, nullptr);
131  m_starttime_valid = true;
132 }
133 
135 {
136  if (!m_cpustat)
137  return "N/A";
138 
139 #ifdef __linux__
140  QString res;
141  m_cpustat->seek(0);
142  m_cpustat->flush();
143 
144  QByteArray line = m_cpustat->readLine(256);
145  if (line.isEmpty())
146  return res;
147 
148  int cores = 0;
149  int ptr = 0;
150  line = m_cpustat->readLine(256);
151  while (!line.isEmpty() && cores < MAX_CORES)
152  {
153  static const int size = sizeof(unsigned long long) * 9;
154  unsigned long long stats[9];
155  memset(stats, 0, size);
156  int num = 0;
157  if (sscanf(line.constData(),
158  "cpu%30d %30llu %30llu %30llu %30llu %30llu "
159  "%30llu %30llu %30llu %30llu %*5000s\n",
160  &num, &stats[0], &stats[1], &stats[2], &stats[3],
161  &stats[4], &stats[5], &stats[6], &stats[7], &stats[8]) >= 4)
162  {
163  float load = stats[0] + stats[1] + stats[2] + stats[4] +
164  stats[5] + stats[6] + stats[7] + stats[8] -
165  m_laststats[ptr + 0] - m_laststats[ptr + 1] -
166  m_laststats[ptr + 2] - m_laststats[ptr + 4] -
167  m_laststats[ptr + 5] - m_laststats[ptr + 6] -
168  m_laststats[ptr + 7] - m_laststats[ptr + 8];
169  float total = load + stats[3] - m_laststats[ptr + 3];
170  if (total > 0)
171  res += QString("%1% ").arg(load / total * 100, 0, 'f', 0);
172  memcpy(&m_laststats[ptr], stats, size);
173  }
174  line = m_cpustat->readLine(256);
175  cores++;
176  ptr += 9;
177  }
178  return res;
179 #else
180  return "N/A";
181 #endif
182 }
bool RecordEndTime()
unsigned long long * m_laststats
Definition: jitterometer.h:65
#define UNIX_PROC_STAT
Definition: jitterometer.cpp:8
QVector< uint > m_times
Definition: jitterometer.h:60
QString m_name
Definition: jitterometer.h:63
void SetNumCycles(int cycles)
QFile * m_cpustat
Definition: jitterometer.h:64
float m_last_fps
Definition: jitterometer.h:61
bool m_starttime_valid
Definition: jitterometer.h:59
bool RecordCycleTime()
Jitterometer(const QString &nname, int ncycles=0)
QString m_lastcpustats
Definition: jitterometer.h:66
#define MAX_CORES
Definition: jitterometer.cpp:9
QString GetCPUStat(void)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
float m_last_sd
Definition: jitterometer.h:62
void RecordStartTime()