From e80eb6fb431c07dbd0a002bb85d1d6b049ffb361 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 3 Jul 2017 15:07:47 +0200 Subject: [PATCH] [General] Get rid of FPS drops --- src/Components/Modules/AntiCheat.cpp | 8 ++-- src/Components/Modules/Changelog.cpp | 2 +- src/Components/Modules/Menus.cpp | 2 +- src/Components/Modules/Node.cpp | 10 +++-- src/Components/Modules/Playlist.cpp | 4 +- src/Components/Modules/Scheduler.cpp | 42 ++++++++++++++++++++ src/Components/Modules/Scheduler.hpp | 11 ++++++ src/Utils/Compression.cpp | 57 +++++++++++++++++++++++++--- src/Utils/Compression.hpp | 4 +- 9 files changed, 121 insertions(+), 19 deletions(-) diff --git a/src/Components/Modules/AntiCheat.cpp b/src/Components/Modules/AntiCheat.cpp index 0e05336a..b488dced 100644 --- a/src/Components/Modules/AntiCheat.cpp +++ b/src/Components/Modules/AntiCheat.cpp @@ -200,8 +200,8 @@ namespace Components void AntiCheat::PerformScan() { - // Perform check only every 10 seconds - if (!AntiCheat::LastCheck.elapsed(10s)) return; + // Perform check only every 20 seconds + if (!AntiCheat::LastCheck.elapsed(20s)) return; AntiCheat::LastCheck.update(); // Hash .text segment @@ -234,7 +234,7 @@ namespace Components static Utils::Time::Interval interval; static std::optional hashVal; - if (!interval.elapsed(11s)) return; + if (!interval.elapsed(32s)) return; interval.update(); // Hash .text segment @@ -256,7 +256,7 @@ namespace Components static Utils::Time::Interval interval; static std::optional hashVal; - if (!interval.elapsed(12s)) return; + if (!interval.elapsed(42s)) return; interval.update(); // Hash .text segment diff --git a/src/Components/Modules/Changelog.cpp b/src/Components/Modules/Changelog.cpp index 2a996293..d92d3004 100644 --- a/src/Components/Modules/Changelog.cpp +++ b/src/Components/Modules/Changelog.cpp @@ -57,7 +57,7 @@ namespace Components UIFeeder::Add(62.0f, Changelog::GetChangelogCount, Changelog::GetChangelogText, Changelog::SelectChangelog); #ifndef DISABLE_ANTICHEAT - Scheduler::OnFrame(AntiCheat::QuickCodeScanner1); + Scheduler::OnFrameAsync(AntiCheat::QuickCodeScanner1); #endif } diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index 33aa0fd4..f76df9d7 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -767,7 +767,7 @@ namespace Components }); #ifndef DISABLE_ANTICHEAT - Scheduler::OnFrame(AntiCheat::QuickCodeScanner2); + Scheduler::OnFrameAsync(AntiCheat::QuickCodeScanner2); #endif Command::Add("mp_QuickMessage", [](Command::Params*) diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 70d67dc2..b7ea148a 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -114,7 +114,7 @@ namespace Components Proto::Node::List list; - std::lock_guard _(Node::Mutex); + Node::Mutex.lock(); for (auto& node : Node::Nodes) { if (node.isValid()) @@ -125,6 +125,7 @@ namespace Components str->append(reinterpret_cast(&addr), sizeof(addr)); } } + Node::Mutex.unlock(); Utils::IO::WriteFile("players/nodes.dat", Utils::Compression::Deflate::ZStd::Compress(list.SerializeAsString())); } @@ -169,8 +170,6 @@ namespace Components ++i; } - - Node::StoreNodes(false); } void Node::Synchronize() @@ -263,6 +262,11 @@ namespace Components if (ZoneBuilder::IsEnabled()) return; Dvar::Register("net_natFix", false, 0, "Fix node registration for certain firewalls/routers"); + Scheduler::OnFrameAsync([]() + { + Node::StoreNodes(false); + }); + Scheduler::OnFrame(Node::RunFrame); Session::Handle("nodeListResponse", Node::HandleResponse); Session::Handle("nodeListRequest", [](Network::Address address, std::string) diff --git a/src/Components/Modules/Playlist.cpp b/src/Components/Modules/Playlist.cpp index 7f6db9c1..bdf5b236 100644 --- a/src/Components/Modules/Playlist.cpp +++ b/src/Components/Modules/Playlist.cpp @@ -39,7 +39,7 @@ namespace Components DWORD Playlist::StorePlaylistStub(const char** buffer) { Playlist::MapRelocation.clear(); - Playlist::CurrentPlaylistBuffer = *buffer; + Playlist::CurrentPlaylistBuffer = Utils::Compression::Deflate::ZStd::Compress(*buffer); return Utils::Hook::Call(0x4C0350)(buffer); } @@ -57,7 +57,7 @@ namespace Components Logger::Print("Received playlist request, sending currently stored buffer.\n"); - std::string compressedList = Utils::Compression::Deflate::ZStd::Compress(Playlist::CurrentPlaylistBuffer); + std::string compressedList = Playlist::CurrentPlaylistBuffer; Proto::Party::Playlist list; list.set_hash(Utils::Cryptography::JenkinsOneAtATime::Compute(compressedList)); diff --git a/src/Components/Modules/Scheduler.cpp b/src/Components/Modules/Scheduler.cpp index 9753923c..a851fbec 100644 --- a/src/Components/Modules/Scheduler.cpp +++ b/src/Components/Modules/Scheduler.cpp @@ -2,6 +2,9 @@ namespace Components { + bool Scheduler::AsyncTerminate; + std::thread Scheduler::AsyncThread; + bool Scheduler::ReadyPassed = false; Utils::Signal Scheduler::ReadySignal; Utils::Signal Scheduler::ShutdownSignal; @@ -10,6 +13,9 @@ namespace Components Utils::Signal Scheduler::FrameOnceSignal; std::vector Scheduler::DelayedSlots; + Utils::Signal Scheduler::AsyncFrameSignal; + Utils::Signal Scheduler::AsyncFrameOnceSignal; + void Scheduler::Once(Utils::Slot callback, bool clientOnly) { if (clientOnly && (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled())) return; @@ -94,6 +100,15 @@ namespace Components Utils::Hook::Call(0x46B370)(num); } + void Scheduler::OnFrameAsync(Utils::Slot callback) + { + Scheduler::AsyncFrameSignal.connect(callback); + } + + void Scheduler::OnceAsync(Utils::Slot callback) + { + Scheduler::AsyncFrameOnceSignal.connect(callback); + } Scheduler::Scheduler() { @@ -101,6 +116,21 @@ namespace Components Scheduler::Once(Scheduler::ReadyHandler); Utils::Hook(0x4D697A, Scheduler::ShutdownStub, HOOK_CALL).install()->quick(); + + Scheduler::AsyncTerminate = false; + Scheduler::AsyncThread = std::thread([]() + { + while (!Scheduler::AsyncTerminate) + { + Scheduler::AsyncFrameSignal(); + + Utils::Signal copy(Scheduler::AsyncFrameOnceSignal); + Scheduler::AsyncFrameOnceSignal.clear(); + copy(); + + std::this_thread::sleep_for(16ms); + } + }); } Scheduler::~Scheduler() @@ -112,6 +142,18 @@ namespace Components Scheduler::FrameOnceSignal.clear(); Scheduler::DelayedSlots.clear(); + Scheduler::AsyncFrameSignal.clear(); + Scheduler::AsyncFrameOnceSignal.clear(); + Scheduler::ReadyPassed = false; } + + void Scheduler::preDestroy() + { + Scheduler::AsyncTerminate = true; + if (Scheduler::AsyncThread.joinable()) + { + Scheduler::AsyncThread.join(); + } + } } diff --git a/src/Components/Modules/Scheduler.hpp b/src/Components/Modules/Scheduler.hpp index b77027b8..7b187b89 100644 --- a/src/Components/Modules/Scheduler.hpp +++ b/src/Components/Modules/Scheduler.hpp @@ -10,12 +10,17 @@ namespace Components Scheduler(); ~Scheduler(); + void preDestroy() override; + static void OnShutdown(Utils::Slot callback); static void OnFrame(Utils::Slot callback, bool clientOnly = false); static void OnReady(Utils::Slot callback, bool clientOnly = false); static void Once(Utils::Slot callback, bool clientOnly = false); static void OnDelay(Utils::Slot callback, std::chrono::nanoseconds delay, bool clientOnly = false); + static void OnFrameAsync(Utils::Slot callback); + static void OnceAsync(Utils::Slot callback); + static void FrameHandler(); private: @@ -27,6 +32,9 @@ namespace Components Utils::Slot callback; }; + static bool AsyncTerminate; + static std::thread AsyncThread; + static Utils::Signal FrameSignal; static Utils::Signal FrameOnceSignal; static std::vector DelayedSlots; @@ -35,6 +43,9 @@ namespace Components static Utils::Signal ReadySignal; static Utils::Signal ShutdownSignal; + static Utils::Signal AsyncFrameSignal; + static Utils::Signal AsyncFrameOnceSignal; + static void ReadyHandler(); static void DelaySignal(); diff --git a/src/Utils/Compression.cpp b/src/Utils/Compression.cpp index 73e5d8c3..1302b448 100644 --- a/src/Utils/Compression.cpp +++ b/src/Utils/Compression.cpp @@ -86,16 +86,61 @@ namespace Utils return Deflate::Decompress(data); } - std::string Deflate::ZStd::Compress(std::string data) + std::string Deflate::ZStd::Compress(std::string data, bool safe) { - Deflate::Semaphore _(DEFLATE_ZSTD); - return Deflate::Compress(data); + if (safe) + { + Utils::Memory::Allocator allocator; + + size_t size = data.size() + 100; + size = ZSTD_compressBound(size); + char* buffer = allocator.allocateArray(size); + + size = ZSTD_compress(buffer, size, data.data(), data.size(), ZSTD_maxCLevel()); + if (size == 0 || ZSTD_isError(size)) return ""; + + return std::string(buffer, size); + } + else + { + Deflate::Semaphore _(DEFLATE_ZSTD); + return Deflate::Compress(data); + } } - std::string Deflate::ZStd::Decompress(std::string data) + std::string Deflate::ZStd::Decompress(std::string data, bool safe) { - Deflate::Semaphore _(DEFLATE_ZSTD); - return Deflate::Decompress(data); + if (safe) + { + if (data.empty()) return ""; + + Utils::Memory::Allocator allocator; + + size_t size = data.size() + 100; + size = ZSTD_compressBound(size); + size_t maxSize = size; + char* buffer = allocator.allocateArray(size); + + while(true) + { + size = ZSTD_decompress(buffer, size, data.data(), data.size()); + if (!ZSTD_isError(size)) break; + + maxSize++; + maxSize *= 2; + size = maxSize; + + allocator.free(buffer); + buffer = allocator.allocateArray(size); + } + + return std::string(buffer, size); + } + else + { + Deflate::Semaphore _(DEFLATE_ZSTD); + return Deflate::Decompress(data); + } } Deflate::Semaphore::Semaphore(bool zstd) diff --git a/src/Utils/Compression.hpp b/src/Utils/Compression.hpp index 1c48fb25..f106b88d 100644 --- a/src/Utils/Compression.hpp +++ b/src/Utils/Compression.hpp @@ -21,8 +21,8 @@ namespace Utils class ZStd { public: - static std::string Compress(std::string data); - static std::string Decompress(std::string data); + static std::string Compress(std::string data, bool safe = true); + static std::string Decompress(std::string data, bool safe = true); }; class Semaphore