From 8cf2f65806bd925a19e2f15d4a027616756d8034 Mon Sep 17 00:00:00 2001 From: Michon <231849@buas.nl> Date: Tue, 29 Sep 2026 18:50:23 +0200 Subject: [PATCH] perf(agc): write each skip report in one call and cap its request dumps mingw's fprintf writes an unbuffered stderr a character at a time: a title skipping many draws spent seconds per frame printing 17 KB RecompileRequest dumps (GTA V ran at 0.1 fps). Reports are built into one string and written once; dumps stop after 8 per reason (APS5_SKIP_REQUEST_DUMPS, -1 for all). Co-Authored-By: Claude Opus 5.5 (1M context) --- .../libSceAgcDriver/Execution/src/Driver.cpp | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver.cpp index c34a57bfa..ffc9e7d40 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver.cpp @@ -1640,15 +1640,47 @@ private: } // A draw or dispatch the translator cannot handle is skipped so the rest of the frame still runs; - // each distinct failure is reported once. static void reportSkip(const char* kind, const std::string& what) { static std::mutex reportedMutex; - static std::set reported; - std::lock_guard lock(reportedMutex); + static std::set reported; + static std::map requestDumps; // APS5_TRACE_SKIPS reports every skip (shortened), not only the first per reason. static const bool traceSkips = std::getenv("APS5_TRACE_SKIPS") != nullptr; - if (reported.insert(what).second) std::fprintf(stderr, "[gpu] skipped %s: %s\n", kind, what.c_str()); - else if (traceSkips) std::fprintf(stderr, "[gpu] skipped %s again: %.100s\n", kind, what.c_str()); + static const int dumpLimit = [] { const char* text = std::getenv("APS5_SKIP_REQUEST_DUMPS"); return text ? std::atoi(text) : 8; }(); + static constexpr std::string_view marker = "\nRecompileRequest:\n"; + std::lock_guard lock(reportedMutex); + std::string line; + static bool announced = false; + if (!announced) { + announced = true; + char text[160]; + std::snprintf(text, sizeof(text), "[gpu] skip reports: one write each, RecompileRequest dumps capped at %d per reason (APS5_SKIP_REQUEST_DUMPS)\n", dumpLimit); + line = text; + } + const std::string prefix = "[gpu] skipped " + std::string(kind); + if (reported.insert(std::hash{}(what)).second) { + const auto request = what.find(marker); + if (request == std::string::npos) { + line += prefix + ": " + what + "\n"; + } else { + const auto reason = what.substr(0, request); + const auto suffix = what.find(' ', request + marker.size()); + auto& dumps = requestDumps[reason]; + if (dumpLimit < 0 || dumps < dumpLimit) { + ++dumps; + line += prefix + ": " + what + "\n"; + } else { + if (dumps == dumpLimit) { + ++dumps; + line += prefix + ": further RecompileRequest dumps for \"" + reason + "\" are left out\n"; + } + line += prefix + ": " + reason + " (request left out)" + (suffix == std::string::npos ? std::string() : what.substr(suffix)) + "\n"; + } + } + } else if (traceSkips) { + line += prefix + " again: " + what.substr(0, 100) + "\n"; + } + if (!line.empty()) std::fwrite(line.data(), 1, line.size(), stderr); } template void tolerate(const char* kind, Work&& work) {