[Libreoffice-commits] online.git: loolwsd/LOOLStress.cpp loolwsd/test

Ashod Nakashian ashod.nakashian at collabora.co.uk
Mon Aug 22 06:01:11 UTC 2016


 loolwsd/LOOLStress.cpp   |   99 ++++++++++++++++++++++++++++++++++++++++-------
 loolwsd/test/helpers.hpp |    8 +--
 2 files changed, 89 insertions(+), 18 deletions(-)

New commits:
commit 5656f844015d9c6e7d70e3bd55fcd313817afb94
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Sun Aug 21 23:34:02 2016 -0400

    loolstress: benchmark statistics are calculated and reported
    
    Statistics include:
    Total latency from input to tile.
    Tile rendering time.
    Tile-cache response time.
    
    The lowest latency for each is reported and the
    95th percentile as well.
    
    The rendering and cache-serving power is
    calculated as Mega-Pixels per second.
    
    Change-Id: Ib1baede818444c92f553eaf3e6b17dc617c51b0f
    Reviewed-on: https://gerrit.libreoffice.org/28310
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/loolwsd/LOOLStress.cpp b/loolwsd/LOOLStress.cpp
index af26b17..8290298 100644
--- a/loolwsd/LOOLStress.cpp
+++ b/loolwsd/LOOLStress.cpp
@@ -77,6 +77,26 @@ using Poco::Util::HelpFormatter;
 using Poco::Util::Option;
 using Poco::Util::OptionSet;
 
+long percentile(std::vector<long>& v, const double percentile)
+{
+    std::sort(v.begin(), v.end());
+
+    const auto N = v.size();
+    const double n = (N - 1) * percentile / 100.0 + 1;
+    if (n <= 1)
+    {
+        return v[0];
+    }
+    else if (n >= N)
+    {
+        return v[N - 1];
+    }
+
+    const auto k = static_cast<int>(n);
+    const double d = n - k;
+    return v[k - 1] + d * (v[k] - v[k - 1]);
+}
+
 /// Connection class with WSD.
 class Connection
 {
@@ -181,21 +201,36 @@ private:
 
     bool modifyDoc(const std::shared_ptr<Connection>& con)
     {
-        const auto start = std::chrono::steady_clock::now();
-
         con->send("key type=input char=97 key=0");
-        if (con->recv("invalidatetiles:").empty())
+        return !con->recv("invalidatetiles:").empty();
+    }
+
+    bool renderTile(const std::shared_ptr<Connection>& con)
+    {
+        const auto startModify = std::chrono::steady_clock::now();
+
+        modifyDoc(con);
+
+        const auto startRendering = std::chrono::steady_clock::now();
+
+        con->send("tilecombine part=0 width=256 height=256 tileposx=0 tileposy=0 tilewidth=3840 tileheight=3840");
+        if (helpers::getTileMessage(*con->getWS(), con->getName()).empty())
         {
             return false;
         }
 
-        const auto delta = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();
-        std::cout << "Round-trip in: " << delta << std::endl;
-        _latencyStats.push_back(delta);
+        const auto now = std::chrono::steady_clock::now();
+
+        const auto deltaRendering = std::chrono::duration_cast<std::chrono::microseconds>(now - startRendering).count();
+        _renderingStats.push_back(deltaRendering);
+
+        const auto deltaModify = std::chrono::duration_cast<std::chrono::microseconds>(now - startModify).count();
+        _latencyStats.push_back(deltaModify);
+
         return true;
     }
 
-    bool fetchTile(const std::shared_ptr<Connection>& con)
+    bool fetchCachedTile(const std::shared_ptr<Connection>& con)
     {
         const auto start = std::chrono::steady_clock::now();
 
@@ -206,8 +241,7 @@ private:
         }
 
         const auto delta = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start).count();
-        std::cout << "Rendered in: " << delta << std::endl;
-        _renderingStats.push_back(delta);
+        _cacheStats.push_back(delta);
         return true;
     }
 
@@ -219,12 +253,12 @@ private:
 
         connection->load();
 
-        for (auto i = 0; i < 100; ++i)
+        for (auto i = 0; i < 10; ++i)
         {
-            modifyDoc(connection);
-        }
+            renderTile(connection);
 
-        fetchTile(connection);
+            fetchCachedTile(connection);
+        }
     }
 
     void replay()
@@ -427,14 +461,17 @@ int Stress::main(const std::vector<std::string>& args)
         return Application::EXIT_NOINPUT;
     }
 
+    std::vector<std::shared_ptr<Worker>> workers;
+
     unsigned index = 0;
     for (unsigned i = 0; i < args.size(); ++i)
     {
         std::cout << "Arg: " << args[i] << std::endl;
         for (unsigned j = 0; j < _numClients; ++j, ++index)
         {
+            workers.emplace_back(new Worker(*this, args[i]));
             clients[index].reset(new Thread());
-            clients[index]->start(*(new Worker(*this, args[i])));
+            clients[index]->start(*workers[workers.size() - 1]);
         }
     }
 
@@ -443,6 +480,40 @@ int Stress::main(const std::vector<std::string>& args)
         client->join();
     }
 
+    if (Stress::Benchmark)
+    {
+        std::vector<long> latencyStats;
+        std::vector<long> renderingStats;
+        std::vector<long> cachedStats;
+
+        for (const auto& worker : workers)
+        {
+            const auto latencyStat = worker->getLatencyStats();
+            latencyStats.insert(latencyStats.end(), latencyStat.begin(), latencyStat.end());
+
+            const auto renderingStat = worker->getRenderingStats();
+            renderingStats.insert(renderingStats.end(), renderingStat.begin(), renderingStat.end());
+
+            const auto cachedStat = worker->getCacheStats();
+            cachedStats.insert(cachedStats.end(), cachedStat.begin(), cachedStat.end());
+        }
+
+        std::cout << "\nResults:\n";
+        std::cout << "Latency best: " << latencyStats[0] << " microsecs, 95th percentile: " << percentile(latencyStats, 95) << " microsecs." << std::endl;
+        std::cout << "Tile best: " << renderingStats[0] << " microsecs, rendering 95th percentile: " << percentile(renderingStats, 95) << " microsecs." << std::endl;
+        std::cout << "Cached best: " << cachedStats[0] << " microsecs, tile 95th percentile: " << percentile(cachedStats, 95) << " microsecs." << std::endl;
+
+        const auto renderingTime = std::accumulate(renderingStats.begin(), renderingStats.end(), 0);
+        const double renderedPixels = 256 * 256 * renderingStats.size();
+        const auto pixelsPerSecRendered = renderedPixels / renderingTime;
+        std::cout << "Rendering power: " << pixelsPerSecRendered << " MPixels/sec." << std::endl;
+
+        const auto cacheTime = std::accumulate(cachedStats.begin(), cachedStats.end(), 0);
+        const double cachePixels = 256 * 256 * cachedStats.size();
+        const auto pixelsPerSecCached = cachePixels / cacheTime;
+        std::cout << "Cache power: " << pixelsPerSecCached << " MPixels/sec." << std::endl;
+    }
+
     return Application::EXIT_OK;
 }
 
diff --git a/loolwsd/test/helpers.hpp b/loolwsd/test/helpers.hpp
index ce6032e..fd7abef 100644
--- a/loolwsd/test/helpers.hpp
+++ b/loolwsd/test/helpers.hpp
@@ -225,7 +225,7 @@ void getResponseMessage(Poco::Net::WebSocket& ws, const std::string& prefix, std
             }
             else
             {
-                std::cerr << "Timeout\n";
+                std::cerr << "Timeout waiting for " << prefix << "\n";
                 --retries;
             }
         }
@@ -296,7 +296,7 @@ std::vector<char> getResponseMessage(Poco::Net::WebSocket& ws, const std::string
             }
             else
             {
-                std::cerr << name << "Timeout\n";
+                std::cerr << name << "Timeout waiting for " << prefix << "\n";
                 --retries;
             }
         }
@@ -404,7 +404,7 @@ void SocketProcessor(const std::string& name,
     {
         if (!socket->poll(waitTime, Poco::Net::Socket::SELECT_READ))
         {
-            std::cerr << name << "Timeout." << std::endl;
+            std::cerr << name << "Timeout polling." << std::endl;
             break;
         }
 
@@ -488,7 +488,7 @@ std::vector<char> getTileMessage(Poco::Net::WebSocket& ws, const std::string& na
         }
         else
         {
-            std::cerr << name << "Timeout\n";
+            std::cerr << name << "Timeout waiting for nextmessage:\n";
             --retries;
         }
     }


More information about the Libreoffice-commits mailing list