Skip to content
Browse files

Add CPU utilisation monitoring (linux only).

The current version is piggybacked onto the jitterometer code (and hence
is playback only - but could easily be moved into one of the 'base'
libraries for more generic use) and extends the jitterometer output as
well as the OSD debug screen.

Utilisation is provided for each core. While overall load is nice, it
doesn't give the real flavour of what's happening when playback is CPU
bound (e.g. the decoder is pegging one core). The output is going to
start looking messy for all of the boys and girls with quad/many core
CPUs and hyperthreading and that will probably need to be tweaked (maybe
overall utilisation plus highlight cores that have utilisation > 90%).

Windows code should be easy enough to produce - not so sure about OS X.
  • Loading branch information...
1 parent 63fc3e5 commit 5aa9f06570f4c2fd732fc011684c0ba3d80ae2ba Mark Kendall committed Jun 30, 2011
View
87 mythtv/libs/libmythtv/jitterometer.cpp
@@ -5,19 +5,46 @@
#include "mythlogging.h"
#include "jitterometer.h"
+#define UNIX_PROC_STAT "/proc/stat"
+#define MAX_CORES 8
+
Jitterometer::Jitterometer(QString nname, int ncycles)
: count(0), num_cycles(ncycles), starttime_valid(0), last_fps(0),
- last_sd(0), name(nname)
+ last_sd(0), name(nname), cpustat(NULL), laststats(NULL)
{
times = (unsigned*) malloc(num_cycles * sizeof(unsigned));
memset(&starttime, 0, sizeof(struct timeval));
if (name.isEmpty())
name = "Jitterometer";
+
+#ifdef __linux__
+ if (QFile::exists(UNIX_PROC_STAT))
+ {
+ cpustat = new QFile(UNIX_PROC_STAT);
+ if (cpustat)
+ {
+ if (!cpustat->open(QIODevice::ReadOnly))
+ {
+ delete cpustat;
+ cpustat = NULL;
+ }
+ else
+ {
+ laststats = new unsigned long long[MAX_CORES * 9];
+ }
+ }
+ }
+#endif
}
Jitterometer::~Jitterometer()
{
+ if (cpustat)
+ cpustat->close();
+ delete cpustat;
+ delete [] laststats;
+
free(times);
}
@@ -81,8 +108,15 @@ bool Jitterometer::RecordEndTime()
if (mean > 0)
last_sd = standard_deviation / mean;
- VERBOSE(VB_PLAYBACK, name + QString("Mean: %1 Std.Dev: %2 fps: %3")
- .arg((int)mean).arg((int)standard_deviation).arg(last_fps, 0, 'f', 2));
+ /* retrieve load if available */
+ QString extra;
+ lastcpustats = GetCPUStat();
+ if (!lastcpustats.isEmpty())
+ extra = QString("CPUs: ") + lastcpustats;
+
+ VERBOSE(VB_PLAYBACK, name + QString("Mean: %1 Std.Dev: %2 fps: %3 ")
+ .arg((int)mean).arg((int)standard_deviation)
+ .arg(last_fps, 0, 'f', 2) + extra);
count = 0;
return true;
@@ -97,3 +131,50 @@ void Jitterometer::RecordStartTime()
gettimeofday(&starttime, NULL);
starttime_valid = 1;
}
+
+QString Jitterometer::GetCPUStat(void)
+{
+ if (!cpustat)
+ return "N/A";
+
+#ifdef __linux__
+ QString res;
+ cpustat->seek(0);
+ cpustat->flush();
+
+ QByteArray line = cpustat->readLine(256);
+ if (line.isEmpty())
+ return res;
+
+ int cores = 0;
+ int ptr = 0;
+ line = cpustat->readLine(256);
+ while (!line.isEmpty() && cores < MAX_CORES)
+ {
+ static const int size = sizeof(unsigned long long) * 9;
+ unsigned long long stats[9];
+ memset(stats, 0, size);
+ int num = 0;
+ if (sscanf(line.constData(),
+ "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %*s\n",
+ &num, &stats[0], &stats[1], &stats[2], &stats[3],
+ &stats[4], &stats[5], &stats[6], &stats[7], &stats[8]) >= 4)
+ {
+ float load = stats[0] + stats[1] + stats[2] + stats[4] +
+ stats[5] + stats[6] + stats[7] + stats[8] -
+ laststats[ptr + 0] - laststats[ptr + 1] -
+ laststats[ptr + 2] - laststats[ptr + 4] -
+ laststats[ptr + 5] - laststats[ptr + 6] -
+ laststats[ptr + 7] - laststats[ptr + 8];
+ float total = load + stats[3] - laststats[ptr + 3];
+ if (total > 0)
+ res += QString("%1% ").arg(load / total * 100, 0, 'f', 0);
+ memcpy(&laststats[ptr], stats, size);
+ }
+ line = cpustat->readLine(256);
+ cores++;
+ ptr += 9;
+ }
+ return res;
+#endif
+}
View
7 mythtv/libs/libmythtv/jitterometer.h
@@ -1,6 +1,8 @@
#ifndef JITTEROMETER_H
#define JITTEROMETER_H
+#include <QFile>
+
/* Jitterometer usage. There are 2 ways to use this:
------------------------------------------------------------------
@@ -38,10 +40,12 @@ class Jitterometer
float GetLastFPS(void) { return last_fps; }
float GetLastSD(void) { return last_sd; }
+ QString GetLastCPUStats(void) { return lastcpustats; }
void SetNumCycles(int cycles);
bool RecordCycleTime();
void RecordStartTime();
bool RecordEndTime();
+ QString GetCPUStat(void);
private:
int count;
@@ -52,6 +56,9 @@ class Jitterometer
float last_fps;
float last_sd;
QString name;
+ QFile *cpustat;
+ unsigned long long *laststats;
+ QString lastcpustats;
};
#endif // JITTEROMETER_H
View
1 mythtv/libs/libmythtv/mythplayer.cpp
@@ -4359,6 +4359,7 @@ void MythPlayer::GetPlaybackData(InfoMap &infoMap)
.arg(output_jmeter->GetLastFPS(), 0, 'f', 2)
.arg(QChar(0xB1, 0))
.arg(output_jmeter->GetLastSD(), 0, 'f', 2);
+ infoMap["load"] = output_jmeter->GetLastCPUStats();
}
GetCodecDescription(infoMap);
}
View
11 mythtv/themes/default-wide/osd.xml
@@ -76,22 +76,23 @@
<font>medium</font>
<area>260,55,150,25</area>
<align>right,vcenter</align>
- <value>Codec :</value>
+ <value>Codec/Dec :</value>
</textarea>
<textarea name="videocodec">
<font>medium</font>
<area>415,55,150,25</area>
<align>left,vcenter</align>
+ <template>%VIDEOCODEC% %VIDEODECODER%</template>
</textarea>
- <textarea name="viddec">
+ <textarea name="cpuload">
<font>medium</font>
<area>260,80,150,25</area>
<align>right,vcenter</align>
- <value>Decoder :</value>
+ <value>CPUs :</value>
</textarea>
- <textarea name="videodecoder">
+ <textarea name="load">
<font>medium</font>
- <area>415,80,150,25</area>
+ <area>415,80,200,25</area>
<align>left,vcenter</align>
</textarea>
View
9 mythtv/themes/default/osd.xml
@@ -76,20 +76,21 @@
<font>medium</font>
<area>176,45,93,20</area>
<align>right,vcenter</align>
- <value>Codec :</value>
+ <value>Codec/Dec :</value>
</textarea>
<textarea name="videocodec">
<font>medium</font>
<area>273,45,93,20</area>
<align>left,vcenter</align>
+ <template>%VIDEOCODEC% %VIDEODECODER%</template>
</textarea>
- <textarea name="viddec">
+ <textarea name="cpuload">
<font>medium</font>
<area>176,66,93,20</area>
<align>right,vcenter</align>
- <value>Decoder :</value>
+ <value>CPUs :</value>
</textarea>
- <textarea name="videodecoder">
+ <textarea name="load">
<font>medium</font>
<area>273,66,93,20</area>
<align>left,vcenter</align>

0 comments on commit 5aa9f06

Please sign in to comment.
Something went wrong with that request. Please try again.