summaryrefslogtreecommitdiffstats
path: root/x0vncserver
diff options
context:
space:
mode:
authorConstantin Kaplinsky <const@tightvnc.com>2005-09-14 16:11:41 +0000
committerConstantin Kaplinsky <const@tightvnc.com>2005-09-14 16:11:41 +0000
commit602f34de072ce7e7cdbcb8a50d2b4e2cfe4416a5 (patch)
tree42495edb4b814cd3e82cf570ea9afe65a3ad974f /x0vncserver
parent384b18ba9233054d4139b6830dc3d74105169958 (diff)
downloadtigervnc-602f34de072ce7e7cdbcb8a50d2b4e2cfe4416a5.tar.gz
tigervnc-602f34de072ce7e7cdbcb8a50d2b4e2cfe4416a5.zip
CPU load monitoring has been implemented in x0vncserver. CPU load
setting defaults to 35% but can be adjusted with new -MaxProcessorUsage parameter. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@319 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'x0vncserver')
-rw-r--r--x0vncserver/CPUMonitor.cxx102
-rw-r--r--x0vncserver/CPUMonitor.h77
-rw-r--r--x0vncserver/Makefile.in2
-rw-r--r--x0vncserver/x0vncserver.cxx34
4 files changed, 210 insertions, 5 deletions
diff --git a/x0vncserver/CPUMonitor.cxx b/x0vncserver/CPUMonitor.cxx
new file mode 100644
index 00000000..e5298bcf
--- /dev/null
+++ b/x0vncserver/CPUMonitor.cxx
@@ -0,0 +1,102 @@
+/* Copyright (C) 2005 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.
+ */
+
+//
+// CPUMonitor.cxx
+//
+
+#include "CPUMonitor.h"
+
+CPUMonitor::CPUMonitor(int optimalLevel, int updatePeriod)
+{
+ setLevel(optimalLevel);
+ setPeriod(updatePeriod);
+ update();
+}
+
+void CPUMonitor::setLevel(int optimalLevel)
+{
+ m_optimalLevel = optimalLevel;
+ if (m_optimalLevel < 0) {
+ m_optimalLevel = 0;
+ } else if (m_optimalLevel > 100) {
+ m_optimalLevel = 100;
+ }
+}
+
+void CPUMonitor::setPeriod(int updatePeriod)
+{
+ m_updatePeriod = (updatePeriod > 10) ? updatePeriod : 10;
+}
+
+void CPUMonitor::update()
+{
+ getClock(&m_savedTime, &m_savedClock);
+}
+
+int CPUMonitor::check()
+{
+ struct timeval timeNow;
+ clock_t clockNow;
+ getClock(&timeNow, &clockNow);
+
+ int coeff = 100; // 100% means no changes.
+
+ if (m_savedClock != (clock_t)-1 && clockNow != (clock_t)-1) {
+
+ // 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);
+ if (timeDiff < m_updatePeriod) {
+ // Measuring CPU usage is problematic in this case. So return
+ // 100 and do not update saved time and clock numbers.
+ return coeff;
+ }
+
+ // Calculate how much processor time has been consumed (in milliseconds).
+ unsigned int clockDiff = (unsigned int)(clockNow - m_savedClock);
+ clockDiff /= (CLOCKS_PER_SEC / 1000);
+
+ // Get actual CPU usage and convert optimal level (to 1/1000).
+ int realUsage = (clockDiff * 1000 + timeDiff/2) / timeDiff;
+ int optimalUsage = m_optimalLevel * 10;
+
+ // Compute correction coefficient (in percents).
+ if (realUsage != 0) {
+ coeff = (optimalUsage * 100 + realUsage/2) / realUsage;
+ } else {
+ coeff = 10000;
+ }
+
+ }
+
+ // Update saved time and clock numbers.
+ m_savedTime = timeNow;
+ m_savedClock = clockNow;
+
+ return coeff;
+}
+
+void CPUMonitor::getClock(struct timeval *tv, clock_t *clk)
+{
+ if (gettimeofday(tv, NULL) != 0) {
+ *clk = (clock_t)-1;
+ } else {
+ *clk = clock();
+ }
+}
diff --git a/x0vncserver/CPUMonitor.h b/x0vncserver/CPUMonitor.h
new file mode 100644
index 00000000..d1165c86
--- /dev/null
+++ b/x0vncserver/CPUMonitor.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2005 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.
+ */
+
+//
+// CPUMonitor.h
+//
+
+#ifndef __CPUMONITOR_H__
+#define __CPUMONITOR_H__
+
+#include <sys/time.h>
+#include <time.h>
+
+class CPUMonitor {
+
+public:
+
+ CPUMonitor(int optimalLevel = 50, int updatePeriod = 1000);
+
+ //
+ // Optimal level is the CPU utilization level to maintain, in
+ // percents.
+ //
+ void setLevel(int optimalLevel);
+
+ //
+ // Update period is the minimum time in milliseconds that has to
+ // pass after update() or check() call, before next check() call
+ // will return meaningful value.
+ //
+ void setPeriod(int updatePeriod);
+
+ //
+ // Save current time and CPU clock, to use in the next check() call.
+ //
+ void update();
+
+ //
+ // This method calculates recent CPU utilization and returns a
+ // percentage factor which would convert current CPU usage into the
+ // optimal value. For example, if the optimal level was set to 40%
+ // and the real value was 50%, the function will return 80, because
+ // 50 * 80% == 40.
+ //
+ // If the CPU utilization cannot be measured, this function returns
+ // 100. This may be the case on the first call to check(), or if the
+ // time period between two successive check() calls was too small.
+ //
+ int check();
+
+protected:
+
+ static void getClock(struct timeval *tv, clock_t *clk);
+
+ int m_optimalLevel;
+ int m_updatePeriod;
+ struct timeval m_savedTime;
+ clock_t m_savedClock;
+
+};
+
+#endif // __CPUMONITOR_H__
diff --git a/x0vncserver/Makefile.in b/x0vncserver/Makefile.in
index 2379ec0a..57d6f22e 100644
--- a/x0vncserver/Makefile.in
+++ b/x0vncserver/Makefile.in
@@ -1,5 +1,5 @@
-SRCS = Image.cxx x0vncserver.cxx
+SRCS = Image.cxx CPUMonitor.cxx x0vncserver.cxx
OBJS = $(SRCS:.cxx=.o)
diff --git a/x0vncserver/x0vncserver.cxx b/x0vncserver/x0vncserver.cxx
index ca96fd7c..f429553a 100644
--- a/x0vncserver/x0vncserver.cxx
+++ b/x0vncserver/x0vncserver.cxx
@@ -35,6 +35,8 @@
#include <network/TcpSocket.h>
#include "Image.h"
+#include "CPUMonitor.h"
+
#include <signal.h>
#include <X11/X.h>
#include <X11/Xlib.h>
@@ -51,8 +53,11 @@ using namespace network;
LogWriter vlog("main");
-IntParameter pollingCycle("PollingCycle", "Milliseconds per one "
- "polling cycle", 50);
+IntParameter pollingCycle("PollingCycle", "Milliseconds per one polling "
+ "cycle; actual interval may be dynamically "
+ "adjusted to satisfy MaxProcessorUsage setting", 50);
+IntParameter maxProcessorUsage("MaxProcessorUsage", "Maximum percentage of "
+ "CPU time to be consumed", 35);
BoolParameter useShm("UseSHM", "Use MIT-SHM extension if available", true);
BoolParameter useOverlay("OverlayMode", "Use overlay mode under "
"IRIX or Solaris", true);
@@ -444,6 +449,9 @@ int main(int argc, char** argv)
if (strlen(hostsFile.getData()) != 0)
listener.setFilter(&fileTcpFilter);
+ CPUMonitor cpumon((int)maxProcessorUsage, 1000);
+ int dynPollingCycle = (int)pollingCycle;
+
struct timeval timeSaved, timeNow;
struct timezone tz;
gettimeofday(&timeSaved, &tz);
@@ -454,7 +462,10 @@ int main(int argc, char** argv)
struct timeval tv;
tv.tv_sec = 0;
- tv.tv_usec = (int)pollingCycle * 1000;
+ tv.tv_usec = dynPollingCycle * 1000;
+ if (tv.tv_usec > 500000) {
+ tv.tv_usec = 500000;
+ }
FD_ZERO(&rfds);
FD_SET(listener.getFd(), &rfds);
@@ -480,6 +491,7 @@ int main(int argc, char** argv)
Socket* sock = listener.accept();
if (sock) {
server.addClient(sock);
+ cpumon.update(); // count time from now
} else {
vlog.status("Client connection rejected");
}
@@ -502,8 +514,22 @@ int main(int argc, char** argv)
if (gettimeofday(&timeNow, &tz) == 0) {
int diff = (int)((timeNow.tv_usec - timeSaved.tv_usec + 500) / 1000 +
(timeNow.tv_sec - timeSaved.tv_sec) * 1000);
- if (diff >= (int)pollingCycle) {
+ if (diff >= dynPollingCycle) {
timeSaved = timeNow;
+ int coeff = cpumon.check();
+ if (coeff < 90 || coeff > 110) {
+ // Adjust polling cycle to satisfy MaxProcessorUsage setting
+ dynPollingCycle = (dynPollingCycle * 100 + coeff/2) / coeff;
+ if (dynPollingCycle < (int)pollingCycle) {
+ dynPollingCycle = (int)pollingCycle;
+ } else if (dynPollingCycle > (int)pollingCycle * 32) {
+ dynPollingCycle = (int)pollingCycle * 32;
+ }
+ // DEBUG:
+ // if (dynPollingCycle != old) {
+ // fprintf(stderr, "[%dms]\t", dynPollingCycle);
+ // }
+ }
desktop.poll();
}
} else {