]> source.dussan.org Git - tigervnc.git/commitdiff
Move encoder statistics into EncodeManager from SMsgWriter
authorPierre Ossman <ossman@cendio.se>
Wed, 11 Feb 2015 16:43:15 +0000 (17:43 +0100)
committerPierre Ossman <ossman@cendio.se>
Fri, 13 Feb 2015 10:13:53 +0000 (11:13 +0100)
It knows more details so it can track things better.

common/rfb/EncodeManager.cxx
common/rfb/EncodeManager.h
common/rfb/SMsgWriter.cxx
common/rfb/SMsgWriter.h

index ca60da488d56a92de20ecaf110fe5d3fdee68235..cd80df97cca016a12c45827aad1ce8e589b14e73 100644 (file)
@@ -23,6 +23,7 @@
 #include <rfb/SConnection.h>
 #include <rfb/SMsgWriter.h>
 #include <rfb/UpdateTracker.h>
+#include <rfb/LogWriter.h>
 
 #include <rfb/RawEncoder.h>
 #include <rfb/RREEncoder.h>
@@ -33,6 +34,8 @@
 
 using namespace rfb;
 
+static LogWriter vlog("EncodeManager");
+
 // Split each rectangle into smaller ones no larger than this area,
 // and no wider than this width.
 static const int SubRectMaxArea = 65536;
@@ -73,8 +76,50 @@ struct RectInfo {
 
 };
 
+static const char *encoderClassName(EncoderClass klass)
+{
+  switch (klass) {
+  case encoderRaw:
+    return "Raw";
+  case encoderRRE:
+    return "RRE";
+  case encoderHextile:
+    return "Hextile";
+  case encoderTight:
+    return "Tight";
+  case encoderTightJPEG:
+    return "Tight (JPEG)";
+  case encoderZRLE:
+    return "ZRLE";
+  }
+
+  return "Unknown Encoder Class";
+}
+
+static const char *encoderTypeName(EncoderType type)
+{
+  switch (type) {
+  case encoderSolid:
+    return "Solid";
+  case encoderBitmap:
+    return "Bitmap";
+  case encoderBitmapRLE:
+    return "Bitmap RLE";
+  case encoderIndexed:
+    return "Indexed";
+  case encoderIndexedRLE:
+    return "Indexed RLE";
+  case encoderFullColour:
+    return "Full Colour";
+  }
+
+  return "Unknown Encoder Type";
+}
+
 EncodeManager::EncodeManager(SConnection* conn_) : conn(conn_)
 {
+  StatsVector::iterator iter;
+
   encoders.resize(encoderClassMax, NULL);
   activeEncoders.resize(encoderTypeMax, encoderRaw);
 
@@ -84,16 +129,78 @@ EncodeManager::EncodeManager(SConnection* conn_) : conn(conn_)
   encoders[encoderTight] = new TightEncoder(conn);
   encoders[encoderTightJPEG] = new TightJPEGEncoder(conn);
   encoders[encoderZRLE] = new ZRLEEncoder(conn);
+
+  updates = 0;
+  stats.resize(encoderClassMax);
+  for (iter = stats.begin();iter != stats.end();++iter) {
+    StatsVector::value_type::iterator iter2;
+    iter->resize(encoderTypeMax);
+    for (iter2 = iter->begin();iter2 != iter->end();++iter2)
+      memset(&*iter2, 0, sizeof(EncoderStats));
+  }
 }
 
 EncodeManager::~EncodeManager()
 {
   std::vector<Encoder*>::iterator iter;
 
+  logStats();
+
   for (iter = encoders.begin();iter != encoders.end();iter++)
     delete *iter;
 }
 
+void EncodeManager::logStats()
+{
+  int i, j;
+
+  unsigned rects;
+  unsigned long long pixels, bytes, equivalent;
+
+  double ratio;
+
+  rects = 0;
+  pixels = bytes = equivalent = 0;
+
+  vlog.info("Framebuffer updates: %u", updates);
+
+  for (i = 0;i < stats.size();i++) {
+    // Did this class do anything at all?
+    for (j = 0;j < stats[i].size();j++) {
+      if (stats[i][j].rects != 0)
+        break;
+    }
+    if (j == stats[i].size())
+      continue;
+
+    vlog.info("  %s:", encoderClassName((EncoderClass)i));
+
+    for (j = 0;j < stats[i].size();j++) {
+      if (stats[i][j].rects == 0)
+        continue;
+
+      rects += stats[i][j].rects;
+      pixels += stats[i][j].pixels;
+      bytes += stats[i][j].bytes;
+      equivalent += stats[i][j].equivalent;
+
+      ratio = (double)stats[i][j].equivalent / stats[i][j].bytes;
+
+      vlog.info("    %s: %u rects, %llu pixels",
+                encoderTypeName((EncoderType)j),
+                stats[i][j].rects, stats[i][j].pixels);
+      vlog.info("    %*s  %llu bytes (%g ratio)",
+                strlen(encoderTypeName((EncoderType)j)), "",
+                stats[i][j].bytes, ratio);
+    }
+  }
+
+  ratio = (double)equivalent / bytes;
+
+  vlog.info("  Total: %u rects, %llu pixels", rects, pixels);
+  vlog.info("         %llu bytes (%g ratio)", bytes, ratio);
+}
+
 bool EncodeManager::supported(int encoding)
 {
   switch (encoding) {
@@ -114,6 +221,8 @@ void EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb,
     int nRects;
     Region changed;
 
+    updates++;
+
     prepareEncoders();
 
     if (conn->cp.supportsLastRect)
@@ -292,6 +401,40 @@ int EncodeManager::computeNumRects(const Region& changed)
   return numRects;
 }
 
+Encoder *EncodeManager::startRect(const Rect& rect, int type)
+{
+  Encoder *encoder;
+  int klass, equiv;
+
+  activeType = type;
+  klass = activeEncoders[activeType];
+
+  beforeLength = conn->getOutStream()->length();
+
+  stats[klass][activeType].rects++;
+  stats[klass][activeType].pixels += rect.area();
+  equiv = 12 + rect.area() * conn->cp.pf().bpp/8;
+  stats[klass][activeType].equivalent += equiv;
+
+  encoder = encoders[klass];
+  conn->writer()->startRect(rect, encoder->encoding);
+
+  return encoder;
+}
+
+void EncodeManager::endRect()
+{
+  int klass;
+  int length;
+
+  conn->writer()->endRect();
+
+  length = conn->getOutStream()->length() - beforeLength;
+
+  klass = activeEncoders[activeType];
+  stats[klass][activeType].bytes += length;
+}
+
 void EncodeManager::writeCopyRects(const UpdateInfo& ui)
 {
   std::vector<Rect> rects;
@@ -362,8 +505,7 @@ void EncodeManager::writeSolidRects(Region *changed, const PixelBuffer* pb)
           }
 
           // Send solid-color rectangle.
-          encoder = encoders[activeEncoders[encoderSolid]];
-          conn->writer()->startRect(erp, encoder->encoding);
+          encoder = startRect(erp, encoderSolid);
           if (encoder->flags & EncoderUseNativePF) {
             encoder->writeSolidRect(erp.width(), erp.height(),
                                     pb->getPF(), colourValue);
@@ -377,7 +519,7 @@ void EncodeManager::writeSolidRects(Region *changed, const PixelBuffer* pb)
             encoder->writeSolidRect(erp.width(), erp.height(),
                                     conn->cp.pf(), converted);
           }
-          conn->writer()->endRect();
+          endRect();
 
           changed->assign_subtract(Region(erp));
 
@@ -507,14 +649,14 @@ void EncodeManager::writeSubRect(const Rect& rect, const PixelBuffer *pb)
       type = encoderIndexed;
   }
 
-  encoder = encoders[activeEncoders[type]];
+  encoder = startRect(rect, type);
 
   if (encoder->flags & EncoderUseNativePF)
     ppb = preparePixelBuffer(rect, pb, false);
 
-  conn->writer()->startRect(rect, encoder->encoding);
   encoder->writeRect(ppb, info.palette);
-  conn->writer()->endRect();
+
+  endRect();
 }
 
 bool EncodeManager::checkSolidTile(const Rect& r, const rdr::U8* colourValue,
index df0275ceeab1b54ae43b50b9c3b77ca8fa739432..a694e063e4eacbcadaf3b14367873890cd2071ae 100644 (file)
@@ -41,6 +41,8 @@ namespace rfb {
     EncodeManager(SConnection* conn);
     ~EncodeManager();
 
+    void logStats();
+
     // Hack to let ConnParams calculate the client's preferred encoding
     static bool supported(int encoding);
 
@@ -52,6 +54,9 @@ namespace rfb {
 
     int computeNumRects(const Region& changed);
 
+    Encoder *startRect(const Rect& rect, int type);
+    void endRect();
+
     void writeCopyRects(const UpdateInfo& ui);
     void writeSolidRects(Region *changed, const PixelBuffer* pb);
     void writeRects(const Region& changed, const PixelBuffer* pb);
@@ -97,6 +102,19 @@ namespace rfb {
     std::vector<Encoder*> encoders;
     std::vector<int> activeEncoders;
 
+    struct EncoderStats {
+      unsigned rects;
+      unsigned long long bytes;
+      unsigned long long pixels;
+      unsigned long long equivalent;
+    };
+    typedef std::vector< std::vector<struct EncoderStats> > StatsVector;
+
+    unsigned updates;
+    StatsVector stats;
+    int activeType;
+    int beforeLength;
+
     class OffsetPixelBuffer : public FullFramePixelBuffer {
     public:
       OffsetPixelBuffer() {}
index 0d61292cbe0026ab5ac7d1289b5c4b2d48b65fac..9aee96d2c3d87ec6465b26313918d9b34bf9fb5a 100644 (file)
@@ -33,31 +33,15 @@ using namespace rfb;
 static LogWriter vlog("SMsgWriter");
 
 SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
-  : cp(cp_), os(os_), currentEncoding(0),
+  : cp(cp_), os(os_),
     nRectsInUpdate(0), nRectsInHeader(0),
     needSetDesktopSize(false), needExtendedDesktopSize(false),
-    needSetDesktopName(false), needSetCursor(false), needSetXCursor(false),
-    lenBeforeRect(0), updatesSent(0), rawBytesEquivalent(0)
+    needSetDesktopName(false), needSetCursor(false), needSetXCursor(false)
 {
-  for (int i = 0; i <= encodingMax; i++) {
-    bytesSent[i] = 0;
-    rectsSent[i] = 0;
-  }
 }
 
 SMsgWriter::~SMsgWriter()
 {
-  vlog.info("framebuffer updates %d",updatesSent);
-  int bytes = 0;
-  for (int i = 0; i <= encodingMax; i++) {
-    if (i != encodingCopyRect)
-      bytes += bytesSent[i];
-    if (rectsSent[i])
-      vlog.info("  %s rects %d, bytes %d",
-                encodingName(i), rectsSent[i], bytesSent[i]);
-  }
-  vlog.info("  raw bytes equivalent %llu, compression ratio %f",
-          rawBytesEquivalent, (double)rawBytesEquivalent / bytes);
 }
 
 void SMsgWriter::writeServerInit()
@@ -276,7 +260,6 @@ void SMsgWriter::writeFramebufferUpdateEnd()
     os->writeU32(pseudoEncodingLastRect);
   }
 
-  updatesSent++;
   endMsg();
 }
 
@@ -293,11 +276,6 @@ void SMsgWriter::startRect(const Rect& r, int encoding)
   if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
     throw Exception("SMsgWriter::startRect: nRects out of sync");
 
-  currentEncoding = encoding;
-  lenBeforeRect = os->length();
-  if (encoding != encodingCopyRect)
-    rawBytesEquivalent += 12 + r.width() * r.height() * (cp->pf().bpp/8);
-
   os->writeS16(r.tl.x);
   os->writeS16(r.tl.y);
   os->writeU16(r.width());
@@ -307,10 +285,6 @@ void SMsgWriter::startRect(const Rect& r, int encoding)
 
 void SMsgWriter::endRect()
 {
-  if (currentEncoding <= encodingMax) {
-    bytesSent[currentEncoding] += os->length() - lenBeforeRect;
-    rectsSent[currentEncoding]++;
-  }
 }
 
 void SMsgWriter::startMsg(int type)
index deddd3cd3b7e2bbd8ce51d957b711d0c0c79dd88..917b933cc05fb2a83d3283359ce359cfdb54ca5a 100644 (file)
@@ -109,11 +109,6 @@ namespace rfb {
     void startRect(const Rect& r, int enc);
     void endRect();
 
-    int getUpdatesSent()           { return updatesSent; }
-    int getRectsSent(int encoding) { return rectsSent[encoding]; }
-    int getBytesSent(int encoding) { return bytesSent[encoding]; }
-    rdr::U64 getRawBytesEquivalent()    { return rawBytesEquivalent; }
-
   protected:
     void startMsg(int type);
     void endMsg();
@@ -137,8 +132,6 @@ namespace rfb {
     ConnParams* cp;
     rdr::OutStream* os;
 
-    int currentEncoding;
-
     int nRectsInUpdate;
     int nRectsInHeader;
 
@@ -149,12 +142,6 @@ namespace rfb {
     bool needSetCursor;
     bool needSetXCursor;
 
-    int lenBeforeRect;
-    int updatesSent;
-    int bytesSent[encodingMax+1];
-    int rectsSent[encodingMax+1];
-    rdr::U64 rawBytesEquivalent;
-
     typedef struct {
       rdr::U16 reason, result;
       int fb_width, fb_height;