Initial commit
This commit is contained in:
240
tests/decperf.cxx
Normal file
240
tests/decperf.cxx
Normal file
@@ -0,0 +1,240 @@
|
||||
/* Copyright 2015 Pierre Ossman <ossman@cendio.se> for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program reads files produced by TightVNC's/TurboVNC's
|
||||
* compare-encodings. It is basically a dump of the RFB protocol
|
||||
* from the server side from the ServerInit message and forward.
|
||||
* It is assumed that the client is using a bgr888 (LE) pixel
|
||||
* format.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <rdr/Exception.h>
|
||||
#include <rdr/FileInStream.h>
|
||||
|
||||
#include <rfb/CConnection.h>
|
||||
#include <rfb/CMsgReader.h>
|
||||
#include <rfb/PixelBuffer.h>
|
||||
#include <rfb/PixelFormat.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
// FIXME: Files are always in this format
|
||||
static const rfb::PixelFormat filePF(32, 24, false, true, 255, 255, 255, 0, 8, 16);
|
||||
|
||||
class CConn : public rfb::CConnection {
|
||||
public:
|
||||
CConn(const char *filename);
|
||||
~CConn();
|
||||
|
||||
virtual void setDesktopSize(int w, int h);
|
||||
virtual void setPixelFormat(const rfb::PixelFormat& pf);
|
||||
virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*);
|
||||
virtual void framebufferUpdateStart();
|
||||
virtual void framebufferUpdateEnd();
|
||||
virtual void setColourMapEntries(int, int, rdr::U16*);
|
||||
virtual void bell();
|
||||
virtual void serverCutText(const char*, rdr::U32);
|
||||
|
||||
public:
|
||||
double cpuTime;
|
||||
|
||||
protected:
|
||||
rdr::FileInStream *in;
|
||||
};
|
||||
|
||||
CConn::CConn(const char *filename)
|
||||
{
|
||||
cpuTime = 0.0;
|
||||
|
||||
in = new rdr::FileInStream(filename);
|
||||
setStreams(in, NULL);
|
||||
|
||||
// Need to skip the initial handshake
|
||||
setState(RFBSTATE_INITIALISATION);
|
||||
// That also means that the reader and writer weren't setup
|
||||
setReader(new rfb::CMsgReader(this, in));
|
||||
}
|
||||
|
||||
CConn::~CConn()
|
||||
{
|
||||
delete in;
|
||||
}
|
||||
|
||||
void CConn::setDesktopSize(int w, int h)
|
||||
{
|
||||
CConnection::setDesktopSize(w, h);
|
||||
|
||||
setFramebuffer(new rfb::ManagedPixelBuffer(filePF, cp.width, cp.height));
|
||||
}
|
||||
|
||||
void CConn::setPixelFormat(const rfb::PixelFormat& pf)
|
||||
{
|
||||
// Override format
|
||||
CConnection::setPixelFormat(filePF);
|
||||
}
|
||||
|
||||
void CConn::setCursor(int, int, const rfb::Point&, const rdr::U8*)
|
||||
{
|
||||
}
|
||||
|
||||
void CConn::framebufferUpdateStart()
|
||||
{
|
||||
CConnection::framebufferUpdateStart();
|
||||
|
||||
startCpuCounter();
|
||||
}
|
||||
|
||||
void CConn::framebufferUpdateEnd()
|
||||
{
|
||||
CConnection::framebufferUpdateEnd();
|
||||
|
||||
endCpuCounter();
|
||||
|
||||
cpuTime += getCpuCounter();
|
||||
}
|
||||
|
||||
void CConn::setColourMapEntries(int, int, rdr::U16*)
|
||||
{
|
||||
}
|
||||
|
||||
void CConn::bell()
|
||||
{
|
||||
}
|
||||
|
||||
void CConn::serverCutText(const char*, rdr::U32)
|
||||
{
|
||||
}
|
||||
|
||||
struct stats
|
||||
{
|
||||
double decodeTime;
|
||||
double realTime;
|
||||
};
|
||||
|
||||
static struct stats runTest(const char *fn)
|
||||
{
|
||||
CConn *cc;
|
||||
struct timeval start, stop;
|
||||
struct stats s;
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
try {
|
||||
cc = new CConn(fn);
|
||||
} catch (rdr::Exception& e) {
|
||||
fprintf(stderr, "Failed to open rfb file: %s\n", e.str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
while (true)
|
||||
cc->processMsg();
|
||||
} catch (rdr::EndOfStream& e) {
|
||||
} catch (rdr::Exception& e) {
|
||||
fprintf(stderr, "Failed to run rfb file: %s\n", e.str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gettimeofday(&stop, NULL);
|
||||
|
||||
s.decodeTime = cc->cpuTime;
|
||||
s.realTime = (double)stop.tv_sec - start.tv_sec;
|
||||
s.realTime += ((double)stop.tv_usec - start.tv_usec)/1000000.0;
|
||||
|
||||
delete cc;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void sort(double *array, int count)
|
||||
{
|
||||
bool sorted;
|
||||
int i;
|
||||
do {
|
||||
sorted = true;
|
||||
for (i = 1;i < count;i++) {
|
||||
if (array[i-1] > array[i]) {
|
||||
double d;
|
||||
d = array[i];
|
||||
array[i] = array[i-1];
|
||||
array[i-1] = d;
|
||||
sorted = false;
|
||||
}
|
||||
}
|
||||
} while (!sorted);
|
||||
}
|
||||
|
||||
static const int runCount = 9;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
struct stats runs[runCount];
|
||||
double values[runCount], dev[runCount];
|
||||
double median, meddev;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Syntax: %s <rfb file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Warmup
|
||||
runTest(argv[1]);
|
||||
|
||||
// Multiple runs to get a good average
|
||||
for (i = 0;i < runCount;i++)
|
||||
runs[i] = runTest(argv[1]);
|
||||
|
||||
// Calculate median and median deviation for CPU usage
|
||||
for (i = 0;i < runCount;i++)
|
||||
values[i] = runs[i].decodeTime;
|
||||
|
||||
sort(values, runCount);
|
||||
median = values[runCount/2];
|
||||
|
||||
for (i = 0;i < runCount;i++)
|
||||
dev[i] = fabs((values[i] - median) / median) * 100;
|
||||
|
||||
sort(dev, runCount);
|
||||
meddev = dev[runCount/2];
|
||||
|
||||
printf("CPU time: %g s (+/- %g %%)\n", median, meddev);
|
||||
|
||||
// And for CPU core usage
|
||||
for (i = 0;i < runCount;i++)
|
||||
values[i] = runs[i].decodeTime / runs[i].realTime;
|
||||
|
||||
sort(values, runCount);
|
||||
median = values[runCount/2];
|
||||
|
||||
for (i = 0;i < runCount;i++)
|
||||
dev[i] = fabs((values[i] - median) / median) * 100;
|
||||
|
||||
sort(dev, runCount);
|
||||
meddev = dev[runCount/2];
|
||||
|
||||
printf("Core usage: %g (+/- %g %%)\n", median, meddev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user