]> source.dussan.org Git - tigervnc.git/commitdiff
Major improvements in algoritms of CPU load balancing. This should
authorConstantin Kaplinsky <const@tightvnc.com>
Fri, 17 Feb 2006 11:29:17 +0000 (11:29 +0000)
committerConstantin Kaplinsky <const@tightvnc.com>
Fri, 17 Feb 2006 11:29:17 +0000 (11:29 +0000)
make polling cycles more regular and changes in CPU load more smooth.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@497 3789f03b-4d11-0410-bbf8-ca57d06f2519

x0vncserver/PollingScheduler.cxx
x0vncserver/PollingScheduler.h
x0vncserver/x0vncserver.cxx

index af597df4b8d388ff89c9d5565afff3e283cb09bb..c9d8d6022f2e18d6e0576c8a449cc452ab7c9842 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
 #include <x0vncserver/PollingScheduler.h>
 
 PollingScheduler::PollingScheduler(int interval, int maxload)
@@ -69,6 +73,7 @@ void PollingScheduler::newPass()
     memset(m_slept, 0, sizeof(m_slept));
     m_sleptSum = 0;
     m_idx = 0;
+    m_count = 0;
 
   } else {
 
@@ -95,26 +100,63 @@ void PollingScheduler::newPass()
     m_errorAbsSum = m_errorAbsSum - abs(oldest) + abs(newError);
 
     //
-    // Here is the most important part.
+    // Below is the most important part.
     // Compute desired duration of the upcoming polling pass.
     //
-    m_ratedDuration = m_interval - m_errorSum;
 
-    int optimalLoadDuration =
-      ((m_durationSum - m_sleptSum) * 900 + m_maxload * 4) / (m_maxload * 8)
-      - m_durationSum;
+    // Estimation based on keeping up constant interval.
+    m_ratedDuration = m_interval - m_errorSum / 2;
+
+    // Estimations based on keeping up desired CPU load.
+    int optimalLoadDuration1 = 0;
+    int optimalLoadDuration8 = 0;
+    int optimalLoadDuration = 0;
+
+    if (m_count > 4) {
+      // Estimation 1 (use previous pass statistics).
+      optimalLoadDuration1 =
+        ((duration - m_sleptThisPass) * 100 + m_maxload/2) / m_maxload;
+
+      if (m_count > 16) {
+        // Estimation 2 (use history of 8 previous passes).
+        optimalLoadDuration8 =
+          ((m_durationSum - m_sleptSum) * 900 + m_maxload*4) / (m_maxload*8)
+          - m_durationSum;
+        // Mix the above two giving more priority to the first.
+        optimalLoadDuration =
+          (2 * optimalLoadDuration1 + optimalLoadDuration8) / 3;
+      } else {
+        optimalLoadDuration = optimalLoadDuration1;
+      }
+    }
+
+#ifdef DEBUG
+    fprintf(stderr, "<est %3d,%3d,%d>\t",
+            m_ratedDuration, optimalLoadDuration1, optimalLoadDuration8);
+#endif
 
+    // Choose final estimation.
     if (m_ratedDuration < optimalLoadDuration) {
       m_ratedDuration = optimalLoadDuration;
     }
-
     if (m_ratedDuration < 0) {
       m_ratedDuration = 0;
+    } else if (m_ratedDuration > 500 && m_interval <= 100) {
+      m_ratedDuration = 500;
+    } else if (m_ratedDuration > 1000) {
+      m_ratedDuration = 1000;
     }
 
-    // Update ring buffer indexer (8 elements in the arrays).
+#ifdef DEBUG
+    fprintf(stderr, "<final est %3d>\t", m_ratedDuration);
+#endif
+
+    // Update ring buffer indexer (8 elements per each arrays).
     m_idx = (m_idx + 1) & 7;
 
+    // Update pass counter.
+    m_count++;
+
   }
 
   m_passStarted = timeNow;
index 025139a11a5e6bdb1d30c72c7390940a306f6043..2e3e5be70b18cb963ca5e3f0625edd661c39791b 100644 (file)
@@ -90,6 +90,8 @@ protected:
   // Indexer for all ring buffers.
   int m_idx;
 
+  // Pass counter.
+  int m_count;
 };
 
 #endif // __POLLINGSCHEDULER_H__
index 30e54162019c00a9c56b914e340e28ad9e4769dc..a9b114f268147160e7d0dc1753c72649ac328a15 100644 (file)
@@ -398,7 +398,7 @@ int main(int argc, char** argv)
         }
         tv.tv_usec = wait_ms * 1000;
 #ifdef DEBUG
-        fprintf(stderr, "[%d]\t", wait_ms);
+        // fprintf(stderr, "[%d]\t", wait_ms);
 #endif
       } else {
         sched.reset();