Skip to content

Commit

Permalink
Add CPU utilisation monitoring (linux only).
Browse files Browse the repository at this point in the history
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
Mark Kendall committed Jun 30, 2011
1 parent 63fc3e5 commit 5aa9f06
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 12 deletions.
87 changes: 84 additions & 3 deletions mythtv/libs/libmythtv/jitterometer.cpp
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand All @@ -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
}
7 changes: 7 additions & 0 deletions 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:
------------------------------------------------------------------
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions mythtv/libs/libmythtv/mythplayer.cpp
Expand Up @@ -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);
}
Expand Down
11 changes: 6 additions & 5 deletions mythtv/themes/default-wide/osd.xml
Expand Up @@ -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>

Expand Down
9 changes: 5 additions & 4 deletions mythtv/themes/default/osd.xml
Expand Up @@ -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>
Expand Down

0 comments on commit 5aa9f06

Please sign in to comment.