From db18cee3361f4ca259b622e699185f60ae302ca8 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen Date: Fri, 3 Sep 2021 15:58:59 +0300 Subject: [PATCH] Add a set of self-microbenchmarks --- common/network/GetAPIMessager.cxx | 5 +- common/rfb/CMakeLists.txt | 1 + common/rfb/EncodeManager.cxx | 6 +- common/rfb/EncodeManager.h | 7 ++ common/rfb/SelfBench.cxx | 197 ++++++++++++++++++++++++++++++ common/rfb/ServerCore.cxx | 4 + common/rfb/ServerCore.h | 1 + common/rfb/VNCServerST.cxx | 5 + unix/xserver/hw/vnc/Xvnc.man | 4 + 9 files changed, 223 insertions(+), 7 deletions(-) create mode 100644 common/rfb/SelfBench.cxx diff --git a/common/network/GetAPIMessager.cxx b/common/network/GetAPIMessager.cxx index 8ecfb67..d7abccd 100644 --- a/common/network/GetAPIMessager.cxx +++ b/common/network/GetAPIMessager.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -32,10 +33,6 @@ using namespace rfb; static LogWriter vlog("GetAPIMessager"); -PixelBuffer *progressiveBilinearScale(const PixelBuffer *pb, - const uint16_t tgtw, const uint16_t tgth, - const float tgtdiff); - struct TightJPEGConfiguration { int quality; int subsampling; diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt index 38d3472..1b37dd5 100644 --- a/common/rfb/CMakeLists.txt +++ b/common/rfb/CMakeLists.txt @@ -48,6 +48,7 @@ set(RFB_SOURCES Security.cxx SecurityServer.cxx SecurityClient.cxx + SelfBench.cxx SSecurityPlain.cxx SSecurityStack.cxx SSecurityVncAuth.cxx diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx index db3add5..565ab16 100644 --- a/common/rfb/EncodeManager.cxx +++ b/common/rfb/EncodeManager.cxx @@ -895,7 +895,7 @@ void EncodeManager::updateVideoStats(const std::vector &rects, const Pixel } } -static PixelBuffer *nearestScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, +PixelBuffer *rfb::nearestScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, const float diff) { ManagedPixelBuffer *newpb = new ManagedPixelBuffer(pb->getPF(), w, h); @@ -920,7 +920,7 @@ static PixelBuffer *nearestScale(const PixelBuffer *pb, const uint16_t w, const return newpb; } -static PixelBuffer *bilinearScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, +PixelBuffer *rfb::bilinearScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, const float diff) { ManagedPixelBuffer *newpb = new ManagedPixelBuffer(pb->getPF(), w, h); @@ -968,7 +968,7 @@ static PixelBuffer *bilinearScale(const PixelBuffer *pb, const uint16_t w, const return newpb; } -PixelBuffer *progressiveBilinearScale(const PixelBuffer *pb, +PixelBuffer *rfb::progressiveBilinearScale(const PixelBuffer *pb, const uint16_t tgtw, const uint16_t tgth, const float tgtdiff) { diff --git a/common/rfb/EncodeManager.h b/common/rfb/EncodeManager.h index 60f7d21..bf47dbf 100644 --- a/common/rfb/EncodeManager.h +++ b/common/rfb/EncodeManager.h @@ -215,6 +215,13 @@ namespace rfb { virtual rdr::U8* getBufferRW(const Rect& r, int* stride); }; }; + + PixelBuffer *nearestScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, + const float diff); + PixelBuffer *bilinearScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, + const float diff); + PixelBuffer *progressiveBilinearScale(const PixelBuffer *pb, const uint16_t w, const uint16_t h, + const float diff); } #endif diff --git a/common/rfb/SelfBench.cxx b/common/rfb/SelfBench.cxx new file mode 100644 index 0000000..fd224d3 --- /dev/null +++ b/common/rfb/SelfBench.cxx @@ -0,0 +1,197 @@ +/* Copyright (C) 2021 Kasm Web + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace rfb; +static LogWriter vlog("SelfBench"); + +static const PixelFormat pfRGBX(32, 24, false, true, 255, 255, 255, 0, 8, 16); + +#define RUNS 64 + +#define W 1600 +#define H 1200 + +void SelfBench() { + + unsigned i, runs; + struct timeval start; + + ManagedPixelBuffer f1(pfRGBX, W, H); + ManagedPixelBuffer f2(pfRGBX, W, H); + ManagedPixelBuffer screen(pfRGBX, W, H); + + int stride; + rdr::U8 *f1ptr = f1.getBufferRW(f1.getRect(), &stride); + rdr::U8 *f2ptr = f2.getBufferRW(f2.getRect(), &stride); + rdr::U8 * const screenptr = screen.getBufferRW(screen.getRect(), &stride); + + rdr::U8 * const f1orig = f1ptr; + rdr::U8 * const f2orig = f2ptr; + + for (i = 0; i < W * H * 4; i += 4) { + f1ptr[0] = rand(); + f1ptr[1] = rand(); + f1ptr[2] = rand(); + + f2ptr[0] = rand(); + f2ptr[1] = rand(); + f2ptr[2] = rand(); + + f1ptr += 4; + f2ptr += 4; + } + + vlog.info("Running micro-benchmarks (single-threaded, runs depending on task)"); + + // Encoding + std::vector vec; + + TightJPEGEncoder jpeg(NULL); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + jpeg.compressOnly(&f1, 8, vec, false); + } + vlog.info("Jpeg compression at quality 8 took %u ms (%u runs)", msSince(&start), runs); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + jpeg.compressOnly(&f1, 4, vec, false); + } + vlog.info("Jpeg compression at quality 4 took %u ms (%u runs)", msSince(&start), runs); + + + TightWEBPEncoder webp(NULL); + + gettimeofday(&start, NULL); + runs = RUNS / 8; + for (i = 0; i < runs; i++) { + webp.compressOnly(&f1, 8, vec, false); + } + vlog.info("Webp compression at quality 8 took %u ms (%u runs)", msSince(&start), runs); + + gettimeofday(&start, NULL); + runs = RUNS / 4; + for (i = 0; i < runs; i++) { + webp.compressOnly(&f1, 4, vec, false); + } + vlog.info("Webp compression at quality 4 took %u ms (%u runs)", msSince(&start), runs); + + // Scaling + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + PixelBuffer *pb = nearestScale(&f1, W * 0.8, H * 0.8, 0.8); + delete pb; + } + vlog.info("Nearest scaling to 80%% took %u ms (%u runs)", msSince(&start), runs); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + PixelBuffer *pb = nearestScale(&f1, W * 0.4, H * 0.4, 0.4); + delete pb; + } + vlog.info("Nearest scaling to 40%% took %u ms (%u runs)", msSince(&start), runs); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + PixelBuffer *pb = bilinearScale(&f1, W * 0.8, H * 0.8, 0.8); + delete pb; + } + vlog.info("Bilinear scaling to 80%% took %u ms (%u runs)", msSince(&start), runs); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + PixelBuffer *pb = bilinearScale(&f1, W * 0.4, H * 0.4, 0.4); + delete pb; + } + vlog.info("Bilinear scaling to 40%% took %u ms (%u runs)", msSince(&start), runs); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + PixelBuffer *pb = progressiveBilinearScale(&f1, W * 0.8, H * 0.8, 0.8); + delete pb; + } + vlog.info("Progressive bilinear scaling to 80%% took %u ms (%u runs)", msSince(&start), runs); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + PixelBuffer *pb = progressiveBilinearScale(&f1, W * 0.4, H * 0.4, 0.4); + delete pb; + } + vlog.info("Progressive bilinear scaling to 40%% took %u ms (%u runs)", msSince(&start), runs); + + // Analysis + ComparingUpdateTracker *comparer = new ComparingUpdateTracker(&screen); + Region cursorReg; + + Server::detectScrolling.setParam(false); + Server::detectHorizontal.setParam(false); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + memcpy(screenptr, i % 2 ? f1orig : f2orig, W * H * 4); + comparer->compare(true, cursorReg); + } + vlog.info("Analysis took %u ms (%u runs) (incl. memcpy overhead)", msSince(&start), runs); + + Server::detectScrolling.setParam(true); + + gettimeofday(&start, NULL); + runs = RUNS; + for (i = 0; i < runs; i++) { + memcpy(screenptr, i % 2 ? f1orig : f2orig, W * H * 4); + comparer->compare(false, cursorReg); + } + vlog.info("Analysis w/ scroll detection took %u ms (%u runs) (incl. memcpy overhead)", msSince(&start), runs); + + Server::detectHorizontal.setParam(true); + delete comparer; + comparer = new ComparingUpdateTracker(&screen); + + gettimeofday(&start, NULL); + runs = RUNS / 2; + for (i = 0; i < runs; i++) { + memcpy(screenptr, i % 2 ? f1orig : f2orig, W * H * 4); + comparer->compare(false, cursorReg); + } + vlog.info("Analysis w/ horizontal scroll detection took %u ms (%u runs) (incl. memcpy overhead)", msSince(&start), runs); + + exit(0); +} diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx index 3b36af0..28ce777 100644 --- a/common/rfb/ServerCore.cxx +++ b/common/rfb/ServerCore.cxx @@ -113,6 +113,10 @@ rfb::BoolParameter rfb::Server::ignoreClientSettingsKasm ("IgnoreClientSettingsKasm", "Ignore the additional client settings exposed in Kasm.", false); +rfb::BoolParameter rfb::Server::selfBench +("SelfBench", + "Run self-benchmarks and exit.", + false); rfb::IntParameter rfb::Server::dynamicQualityMin ("DynamicQualityMin", "The minimum dynamic JPEG quality, 0 = low, 9 = high", diff --git a/common/rfb/ServerCore.h b/common/rfb/ServerCore.h index 280596f..766eda0 100644 --- a/common/rfb/ServerCore.h +++ b/common/rfb/ServerCore.h @@ -74,6 +74,7 @@ namespace rfb { static BoolParameter detectScrolling; static BoolParameter detectHorizontal; static BoolParameter ignoreClientSettingsKasm; + static BoolParameter selfBench; static PresetParameter preferBandwidth; }; diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index a564021..785ab42 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -76,6 +76,8 @@ static LogWriter slog("VNCServerST"); LogWriter VNCServerST::connectionsLog("Connections"); EncCache VNCServerST::encCache; +void SelfBench(); + // // -=- VNCServerST Implementation // @@ -212,6 +214,9 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_) } trackingClient[0] = 0; + + if (Server::selfBench) + SelfBench(); } VNCServerST::~VNCServerST() diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man index 809fc1c..f3a6ac6 100644 --- a/unix/xserver/hw/vnc/Xvnc.man +++ b/unix/xserver/hw/vnc/Xvnc.man @@ -317,6 +317,10 @@ Log clipboard and keyboard actions. Info logs just clipboard direction and size, verbose adds the contents for both. . .TP +.B \-selfBench +Run a set of self-benchmarks and exit. +. +.TP .B \-noWebsocket Disable websockets and expose a traditional VNC port (5901, etc.). .