From 79eb18553053014ccbbd30361f6a1a1a6f4f7dc6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 25 Dec 2025 23:39:11 +0300 Subject: [PATCH] reduce copies in ThreadPool --- src/assets/AssetsLoader.cpp | 2 +- src/graphics/render/BlocksRenderer.cpp | 2 +- src/graphics/render/BlocksRenderer.hpp | 4 ++-- src/graphics/render/ChunksRenderer.cpp | 24 +++++++++++++----------- src/graphics/render/commons.hpp | 8 ++++---- src/util/ThreadPool.hpp | 19 +++++++++++++------ src/world/files/WorldConverter.cpp | 2 +- 7 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 49ce5e04d..f717c1e5b 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -354,7 +354,7 @@ std::shared_ptr AssetsLoader::startTask(runnable onDone) { std::make_shared>( "assets-loader-pool", [=]() { return std::make_shared(this); }, - [this](const assetload::postfunc& func) { func(&assets); } + [this](assetload::postfunc&& func) { func(&assets); } ); pool->setOnComplete(std::move(onDone)); while (!entries.empty()) { diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 5320edd73..64f8811f1 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -785,7 +785,7 @@ ChunkMesh BlocksRenderer::render( IndexBufferData {indexBuffer.get(), indexCount}, IndexBufferData {denseIndexBuffer.get(), denseIndexCount}, } - ), std::move(sortingMesh)}; + ), std::move(sortingMesh), nullptr}; } size_t BlocksRenderer::getMemoryConsumption() const { diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index 56a24b472..1eee81783 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -21,7 +21,7 @@ class VoxelsVolume; class ContentGfxCache; struct UVRegion; -class BlocksRenderer { +class BlocksRenderer final { public: BlocksRenderer( size_t capacity, @@ -29,7 +29,7 @@ public: const ContentGfxCache& cache, const EngineSettings& settings ); - virtual ~BlocksRenderer(); + ~BlocksRenderer(); void build(const Chunk* chunk, const VoxelsVolume& volume); ChunkMesh render( diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 78bf6f2e7..b906b9b5e 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -73,14 +73,16 @@ ChunksRenderer::ChunksRenderer( *level, cache, settings ); }, - [&](RendererResult& result) { - if (!result.cancelled) { - auto meshData = std::move(result.meshData); - meshes[result.key] = ChunkMesh { - std::make_unique>(meshData.mesh), - std::move(meshData.sortingMesh)}; - } - inwork.erase(result.key); + [&](RendererResult&& result) { + if (!result.cancelled) { + auto meshData = std::move(result.meshData); + auto chunk = std::make_unique>(meshData.mesh); + meshes[result.key] = ChunkMesh { + std::move(chunk), + std::move(meshData.sortingMesh), + nullptr}; + } + inwork.erase(result.key); }, settings.graphics.chunkMaxRenderers.get() ) { @@ -130,8 +132,8 @@ const Mesh* ChunksRenderer::render( auto voxelsBuffer = prepareVoxelsVolume(*chunk); auto mesh = renderer->render(chunk.get(), *voxelsBuffer); - meshes[key] = - ChunkMesh {std::move(mesh.mesh), std::move(mesh.sortingMeshData)}; + meshes[key] = ChunkMesh { + std::move(mesh.mesh), std::move(mesh.sortingMeshData), nullptr}; return meshes[key].mesh.get(); } if (inwork.find(key) != inwork.end()) { @@ -174,7 +176,7 @@ const Mesh* ChunksRenderer::getOrRender( } void ChunksRenderer::update() { - threadPool.update(); + threadPool.pullResults(); } const Mesh* ChunksRenderer::retrieveChunk( diff --git a/src/graphics/render/commons.hpp b/src/graphics/render/commons.hpp index 9e78d1f53..5118f9c7d 100644 --- a/src/graphics/render/commons.hpp +++ b/src/graphics/render/commons.hpp @@ -1,14 +1,14 @@ #pragma once +#include "graphics/core/MeshData.hpp" +#include "util/Buffer.hpp" + #include #include #include #include #include -#include "graphics/core/MeshData.hpp" -#include "util/Buffer.hpp" - /// @brief Chunk mesh vertex format struct ChunkVertex { glm::vec3 position; @@ -49,5 +49,5 @@ struct ChunkMeshData { struct ChunkMesh { std::unique_ptr> mesh; SortingMeshData sortingMeshData; - std::unique_ptr > sortedMesh = nullptr; + std::unique_ptr > sortedMesh; }; diff --git a/src/util/ThreadPool.hpp b/src/util/ThreadPool.hpp index 98ebcce5b..90b7aad14 100644 --- a/src/util/ThreadPool.hpp +++ b/src/util/ThreadPool.hpp @@ -42,7 +42,7 @@ namespace util { std::condition_variable jobsMutexCondition; std::mutex jobsMutex; std::vector> workersBlocked; - consumer resultConsumer; + consumer resultConsumer; consumer onJobFailed = nullptr; runnable onComplete = nullptr; std::atomic busyWorkers = 0; @@ -116,7 +116,7 @@ namespace util { ThreadPool( std::string name, supplier>> workersSupplier, - consumer resultConsumer, + consumer resultConsumer, int maxWorkers=UNLIMITED ) : logger(std::move(name)), resultConsumer(resultConsumer) { @@ -178,22 +178,28 @@ namespace util { } void update() override { + pullResults(); + } + + size_t pullResults(size_t maxResults = -1) { if (!working) { - return; + return 0; } if (failed) { throw std::runtime_error("some job failed"); } bool complete = false; + size_t resultsProcessed = 0; { std::lock_guard lock(resultsMutex); - while (!results.empty()) { - ThreadPoolResult entry = results.front(); + while (!results.empty() && resultsProcessed < maxResults) { + ThreadPoolResult entry = std::move(results.front()); results.pop(); + ++resultsProcessed; try { - resultConsumer(entry.entry); + resultConsumer(std::move(entry.entry)); } catch (std::exception& err) { logger.error() << err.what(); if (onJobFailed) { @@ -227,6 +233,7 @@ namespace util { if (complete) { terminate(); } + return resultsProcessed; } void enqueueJob(T job) { diff --git a/src/world/files/WorldConverter.cpp b/src/world/files/WorldConverter.cpp index 2f116d22e..431d4c41c 100644 --- a/src/world/files/WorldConverter.cpp +++ b/src/world/files/WorldConverter.cpp @@ -163,7 +163,7 @@ std::shared_ptr WorldConverter::startTask( auto pool = std::make_shared>( "converter-pool", [=]() { return std::make_shared(converter); }, - [=](int&) {} + [=](int&&) {} ); auto& converterTasks = converter->tasks; while (!converterTasks.empty()) {