arithmetics with microseconds, to make the code clearer. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@489 3789f03b-4d11-0410-bbf8-ca57d06f2519tags/v0.0.90
int CPUMonitor::check() | int CPUMonitor::check() | ||||
{ | { | ||||
struct timeval timeNow; | |||||
TimeMillis timeNow; | |||||
clock_t clockNow; | clock_t clockNow; | ||||
getClock(&timeNow, &clockNow); | getClock(&timeNow, &clockNow); | ||||
if (m_savedClock != (clock_t)-1 && clockNow != (clock_t)-1) { | if (m_savedClock != (clock_t)-1 && clockNow != (clock_t)-1) { | ||||
// Find out how much real time has been elapsed (in milliseconds). | // Find out how much real time has been elapsed (in milliseconds). | ||||
int timeDiff = (int)((timeNow.tv_usec - m_savedTime.tv_usec + 500) / 1000 + | |||||
(timeNow.tv_sec - m_savedTime.tv_sec) * 1000); | |||||
int timeDiff = timeNow.diffFrom(m_savedTime); | |||||
if (timeDiff < m_updatePeriod) { | if (timeDiff < m_updatePeriod) { | ||||
// Measuring CPU usage is problematic in this case. So return | // Measuring CPU usage is problematic in this case. So return | ||||
// 100 and do not update saved time and clock numbers. | // 100 and do not update saved time and clock numbers. | ||||
return coeff; | return coeff; | ||||
} | } | ||||
void CPUMonitor::getClock(struct timeval *tv, clock_t *clk) | |||||
void CPUMonitor::getClock(TimeMillis *tm, clock_t *clk) | |||||
{ | { | ||||
if (gettimeofday(tv, NULL) != 0) { | |||||
*clk = (clock_t)-1; | |||||
} else { | |||||
if (tm->update()) { | |||||
*clk = clock(); | *clk = clock(); | ||||
} else { | |||||
*clk = (clock_t)-1; | |||||
} | } | ||||
} | } |
#ifndef __CPUMONITOR_H__ | #ifndef __CPUMONITOR_H__ | ||||
#define __CPUMONITOR_H__ | #define __CPUMONITOR_H__ | ||||
#include <sys/time.h> | |||||
#include <time.h> | #include <time.h> | ||||
#include <x0vncserver/TimeMillis.h> | |||||
class CPUMonitor { | class CPUMonitor { | ||||
public: | public: | ||||
protected: | protected: | ||||
static void getClock(struct timeval *tv, clock_t *clk); | |||||
static void getClock(TimeMillis *tm, clock_t *clk); | |||||
int m_optimalLevel; | int m_optimalLevel; | ||||
int m_updatePeriod; | int m_updatePeriod; | ||||
struct timeval m_savedTime; | |||||
TimeMillis m_savedTime; | |||||
clock_t m_savedClock; | clock_t m_savedClock; | ||||
}; | }; |
#include <rfb/Configuration.h> | #include <rfb/Configuration.h> | ||||
#include <rfb/ServerCore.h> | #include <rfb/ServerCore.h> | ||||
#include <x0vncserver/Image.h> | |||||
#include <x0vncserver/PollingManager.h> | #include <x0vncserver/PollingManager.h> | ||||
BoolParameter PollingManager::pollPointer | BoolParameter PollingManager::pollPointer | ||||
memset(m_rateMatrix, 0, numTiles); | memset(m_rateMatrix, 0, numTiles); | ||||
memset(m_videoFlags, 0, numTiles); | memset(m_videoFlags, 0, numTiles); | ||||
memset(m_changedFlags, 0, numTiles); | memset(m_changedFlags, 0, numTiles); | ||||
#ifdef DEBUG | |||||
memset(&m_timeSaved, 0, sizeof(m_timeSaved)); | |||||
#endif | |||||
} | } | ||||
PollingManager::~PollingManager() | PollingManager::~PollingManager() | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
void PollingManager::debugBeforePoll() | void PollingManager::debugBeforePoll() | ||||
{ | { | ||||
struct timeval timeNow; | |||||
struct timezone tz; | |||||
gettimeofday(&timeNow, &tz); | |||||
int diff = (int)((timeNow.tv_usec - m_timeSaved.tv_usec + 500) / 1000 + | |||||
(timeNow.tv_sec - m_timeSaved.tv_sec) * 1000); | |||||
TimeMillis timeNow; | |||||
int diff = timeNow.diffFrom(m_timeSaved); | |||||
fprintf(stderr, "[wait%4dms]\t[step %2d]\t", diff, m_pollingStep % 32); | fprintf(stderr, "[wait%4dms]\t[step %2d]\t", diff, m_pollingStep % 32); | ||||
m_timeSaved = timeNow; | m_timeSaved = timeNow; | ||||
} | } | ||||
void PollingManager::debugAfterPoll() | void PollingManager::debugAfterPoll() | ||||
{ | { | ||||
struct timeval timeNow; | |||||
struct timezone tz; | |||||
gettimeofday(&timeNow, &tz); | |||||
int diff = (int)((timeNow.tv_usec - m_timeSaved.tv_usec + 500) / 1000 + | |||||
(timeNow.tv_sec - m_timeSaved.tv_sec) * 1000); | |||||
TimeMillis timeNow; | |||||
int diff = timeNow.diffFrom(m_timeSaved); | |||||
fprintf(stderr, "[poll%4dms]\n", diff); | fprintf(stderr, "[poll%4dms]\n", diff); | ||||
m_timeSaved = timeNow; | m_timeSaved = timeNow; | ||||
} | } |
#ifndef __POLLINGMANAGER_H__ | #ifndef __POLLINGMANAGER_H__ | ||||
#define __POLLINGMANAGER_H__ | #define __POLLINGMANAGER_H__ | ||||
#include <sys/time.h> | |||||
#include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
#include <rfb/VNCServer.h> | #include <rfb/VNCServer.h> | ||||
#include <x0vncserver/Image.h> | #include <x0vncserver/Image.h> | ||||
#ifdef DEBUG | |||||
#include <x0vncserver/TimeMillis.h> | |||||
#endif | |||||
using namespace rfb; | using namespace rfb; | ||||
class PollingManager { | class PollingManager { | ||||
void debugBeforePoll(); | void debugBeforePoll(); | ||||
void debugAfterPoll(); | void debugAfterPoll(); | ||||
struct timeval m_timeSaved; | |||||
TimeMillis m_timeSaved; | |||||
#endif | #endif | ||||
}; | }; |
/* Copyright (C) 2006 Constantin Kaplinsky. All Rights Reserved. | |||||
* | |||||
* 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. | |||||
*/ | |||||
// | |||||
// TimeMillis.cxx | |||||
// | |||||
#include <x0vncserver/TimeMillis.h> | |||||
TimeMillis::TimeMillis() | |||||
{ | |||||
update(); | |||||
} | |||||
bool TimeMillis::update() | |||||
{ | |||||
struct timezone tz; | |||||
return (gettimeofday(&m_timeval, &tz) == 0); | |||||
} | |||||
int TimeMillis::diffFrom(const TimeMillis &older) const | |||||
{ | |||||
int diff = (int) | |||||
((m_timeval.tv_usec - older.m_timeval.tv_usec + 500) / 1000 + | |||||
(m_timeval.tv_sec - older.m_timeval.tv_sec) * 1000); | |||||
return diff; | |||||
} | |||||
/* Copyright (C) 2006 Constantin Kaplinsky. All Rights Reserved. | |||||
* | |||||
* 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. | |||||
*/ | |||||
// | |||||
// TimeMillis.h | |||||
// | |||||
#ifndef __TIMEMILLIS_H__ | |||||
#define __TIMEMILLIS_H__ | |||||
#include <sys/time.h> | |||||
class TimeMillis { | |||||
public: | |||||
TimeMillis(); | |||||
// Set this object to current time, returns true on sucess. | |||||
bool update(); | |||||
// Return difference in milliseconds between two time points. | |||||
int diffFrom(const TimeMillis &older) const; | |||||
protected: | |||||
struct timeval m_timeval; | |||||
}; | |||||
#endif // __TIMEMILLIS_H__ | |||||
// e.g. 800x600. | // e.g. 800x600. | ||||
#include <strings.h> | #include <strings.h> | ||||
#include <sys/time.h> | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <x0vncserver/Image.h> | #include <x0vncserver/Image.h> | ||||
#include <x0vncserver/PollingManager.h> | #include <x0vncserver/PollingManager.h> | ||||
#include <x0vncserver/CPUMonitor.h> | #include <x0vncserver/CPUMonitor.h> | ||||
#include <x0vncserver/TimeMillis.h> | |||||
using namespace rfb; | using namespace rfb; | ||||
using namespace network; | using namespace network; | ||||
exit(1); | exit(1); | ||||
} | } | ||||
// | |||||
// Adjust polling cycle to satisfy MaxProcessorUsage setting. | |||||
// | |||||
static void adjustPollingCycle(int *cycle, CPUMonitor *mon) | |||||
{ | |||||
int coeff = mon->check(); | |||||
if (coeff < 90 || coeff > 110) { | |||||
#ifdef DEBUG | |||||
int oldPollingCycle = *cycle; | |||||
#endif | |||||
*cycle = (*cycle * 100 + coeff/2) / coeff; | |||||
if (*cycle < (int)pollingCycle) { | |||||
*cycle = (int)pollingCycle; | |||||
} else if (*cycle > (int)pollingCycle * 32) { | |||||
*cycle = (int)pollingCycle * 32; | |||||
} | |||||
#ifdef DEBUG | |||||
if (*cycle != oldPollingCycle) | |||||
fprintf(stderr, "\t[new cycle %dms]\n", *cycle); | |||||
#endif | |||||
} | |||||
} | |||||
int main(int argc, char** argv) | int main(int argc, char** argv) | ||||
{ | { | ||||
initStdIOLoggers(); | initStdIOLoggers(); | ||||
CPUMonitor cpumon((int)maxProcessorUsage, 1000); | CPUMonitor cpumon((int)maxProcessorUsage, 1000); | ||||
int dynPollingCycle = (int)pollingCycle; | int dynPollingCycle = (int)pollingCycle; | ||||
struct timeval timeSaved, timeNow; | |||||
struct timezone tz; | |||||
gettimeofday(&timeSaved, &tz); | |||||
timeSaved.tv_sec -= 60; | |||||
TimeMillis timeSaved, timeNow; | |||||
while (true) { | while (true) { | ||||
fd_set rfds; | fd_set rfds; | ||||
struct timeval tv; | struct timeval tv; | ||||
// FIXME: This seems to be wrong. | |||||
tv.tv_sec = 0; | tv.tv_sec = 0; | ||||
tv.tv_usec = dynPollingCycle * 1000; | tv.tv_usec = dynPollingCycle * 1000; | ||||
if (tv.tv_usec > 500000) { | if (tv.tv_usec > 500000) { | ||||
server.checkTimeouts(); | server.checkTimeouts(); | ||||
if (gettimeofday(&timeNow, &tz) == 0) { | |||||
int diff = (int)((timeNow.tv_usec - timeSaved.tv_usec + 500) / 1000 + | |||||
(timeNow.tv_sec - timeSaved.tv_sec) * 1000); | |||||
if (timeNow.update()) { | |||||
int diff = timeNow.diffFrom(timeSaved); | |||||
if (diff >= dynPollingCycle) { | if (diff >= dynPollingCycle) { | ||||
adjustPollingCycle(&dynPollingCycle, &cpumon); | |||||
timeSaved = timeNow; | timeSaved = timeNow; | ||||
int coeff = cpumon.check(); | |||||
if (coeff < 90 || coeff > 110) { | |||||
// Adjust polling cycle to satisfy MaxProcessorUsage setting | |||||
#ifdef DEBUG | |||||
int oldPollingCycle = dynPollingCycle; | |||||
#endif | |||||
dynPollingCycle = (dynPollingCycle * 100 + coeff/2) / coeff; | |||||
if (dynPollingCycle < (int)pollingCycle) { | |||||
dynPollingCycle = (int)pollingCycle; | |||||
} else if (dynPollingCycle > (int)pollingCycle * 32) { | |||||
dynPollingCycle = (int)pollingCycle * 32; | |||||
} | |||||
#ifdef DEBUG | |||||
if (dynPollingCycle != oldPollingCycle) | |||||
fprintf(stderr, "\t[new cycle %dms]\n", dynPollingCycle); | |||||
#endif | |||||
} | |||||
desktop.poll(); | desktop.poll(); | ||||
} | } | ||||
} else { | } else { | ||||
// Something strange has happened -- gettimeofday(2) failed. | |||||
// Something strange has happened -- TimeMillis::update() failed. | |||||
// Poll after each select(), as in the original VNC4 code. | // Poll after each select(), as in the original VNC4 code. | ||||
desktop.poll(); | desktop.poll(); | ||||
} | } |