From 463a8cd751ec913f0b86d252ff6ae1ce085906f2 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 10:57:18 -0700 Subject: [PATCH] feat(extract): expose --threads to upgrade-extract + report elapsed time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit emitOpenFormats now takes an optional threadCount parameter (0 = auto). The asset_extract --upgrade-extract path forwards opts.threads so users can override the auto-detect when running on a CI machine with limited cores or wanting deterministic timing. Also wraps the upgrade pass with a chrono timer and prints elapsed seconds so the parallelization payoff is visible at a glance: asset_extract --upgrade-extract Data/expansions/wotlk --threads 8 Walking Data/expansions/wotlk for open-format upgrades... elapsed : 47.2 s PNG (BLP→PNG) : 12340 ok ... Verified end-to-end: --threads 2 on 5 hand-built DBCs converts all 5 in well under a second. --- tools/asset_extract/main.cpp | 9 ++++++++- tools/asset_extract/open_format_emitter.cpp | 6 ++++-- tools/asset_extract/open_format_emitter.hpp | 4 +++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/asset_extract/main.cpp b/tools/asset_extract/main.cpp index 697d798e..3e36da97 100644 --- a/tools/asset_extract/main.cpp +++ b/tools/asset_extract/main.cpp @@ -1,5 +1,6 @@ #include "extractor.hpp" #include "open_format_emitter.hpp" +#include #include #include #include @@ -120,11 +121,17 @@ int main(int argc, char** argv) { } std::cout << "Walking " << upgradeDir << " for open-format upgrades...\n"; + auto t0 = std::chrono::steady_clock::now(); wowee::tools::OpenFormatStats stats; + // Pass 0 to auto-detect threads (or honor user --threads override). + unsigned int t = opts.threads > 0 ? static_cast(opts.threads) : 0; wowee::tools::emitOpenFormats(upgradeDir, opts.emitPng, opts.emitJsonDbc, opts.emitWom, opts.emitWob, - opts.emitTerrain, stats); + opts.emitTerrain, stats, t); + auto secs = std::chrono::duration_cast( + std::chrono::steady_clock::now() - t0).count() / 1000.0; + std::cout << " elapsed : " << secs << " s\n"; std::cout << " PNG (BLP→PNG) : " << stats.pngOk << " ok" << (stats.pngFail ? ", " + std::to_string(stats.pngFail) + " failed" : "") << "\n"; std::cout << " JSON (DBC→JSON) : " << stats.jsonDbcOk << " ok" diff --git a/tools/asset_extract/open_format_emitter.cpp b/tools/asset_extract/open_format_emitter.cpp index 207c8b1a..c470bc29 100644 --- a/tools/asset_extract/open_format_emitter.cpp +++ b/tools/asset_extract/open_format_emitter.cpp @@ -289,7 +289,8 @@ void emitOpenFormats(const std::string& rootDir, bool emitPng, bool emitJsonDbc, bool emitWom, bool emitWob, bool emitTerrain, - OpenFormatStats& stats) { + OpenFormatStats& stats, + unsigned int threadCount) { if (!fs::exists(rootDir)) return; if (!emitPng && !emitJsonDbc && !emitWom && !emitWob && !emitTerrain) return; @@ -368,7 +369,8 @@ void emitOpenFormats(const std::string& rootDir, } }; - unsigned int threadCount = std::max(1u, std::thread::hardware_concurrency()); + if (threadCount == 0) threadCount = std::thread::hardware_concurrency(); + if (threadCount == 0) threadCount = 1; std::vector pool; pool.reserve(threadCount); for (unsigned int t = 0; t < threadCount; t++) pool.emplace_back(worker); diff --git a/tools/asset_extract/open_format_emitter.hpp b/tools/asset_extract/open_format_emitter.hpp index 6c6c96b3..0a2b0b18 100644 --- a/tools/asset_extract/open_format_emitter.hpp +++ b/tools/asset_extract/open_format_emitter.hpp @@ -50,11 +50,13 @@ bool emitTerrainFromAdt(const std::string& adtPath, const std::string& outBase); // Walk an extracted-asset directory and emit open-format side-files for // every requested format. Counts accumulated into stats. +// `threadCount` 0 = auto-detect from hardware_concurrency(). void emitOpenFormats(const std::string& rootDir, bool emitPng, bool emitJsonDbc, bool emitWom, bool emitWob, bool emitTerrain, - OpenFormatStats& stats); + OpenFormatStats& stats, + unsigned int threadCount = 0); } // namespace tools } // namespace wowee