diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index 0060738dad..a4b539055a 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -4659,6 +4659,7 @@ struct spu_llvm u32 worker_index = 0; u32 notify_compile_count = 0; + u32 compile_pending = 0; std::vector notify_compile(worker_count); m_workers = make_single>("SPUW.", worker_count); @@ -4689,7 +4690,7 @@ struct spu_llvm { if (notify_compile[i]) { - (workers.begin() + (i % worker_count))->registered.notify(); + (workers.begin() + i)->registered.notify(); } } } @@ -4700,6 +4701,7 @@ struct spu_llvm add_count = 65535; // Reset count std::fill(notify_compile.begin(), notify_compile.end(), 0); // Reset notification flags notify_compile_count = 0; + compile_pending = 0; continue; } @@ -4740,18 +4742,26 @@ struct spu_llvm { notify_compile[worker_index % worker_count] = 1; notify_compile_count++; + } - if (notify_compile_count == notify_compile.size()) + compile_pending++; + + // Notify all before queue runs out if there is considerable excess + // Optimized that: if there are many workers, it acts soon + // If there are only a few workers, it postpones notifications until there is some more workload + if (notify_compile_count && std::min(7, utils::aligned_div(worker_count * 2, 3) + 2) <= compile_pending) + { + for (usz i = 0; i < worker_count; i++) { - // Notify all - for (usz i = 0; i < worker_count; i++) + if (notify_compile[i]) { - (workers.begin() + (i % worker_count))->registered.notify(); + (workers.begin() + i)->registered.notify(); } - - std::fill(notify_compile.begin(), notify_compile.end(), 0); // Reset notification flags - notify_compile_count = 0; } + + std::fill(notify_compile.begin(), notify_compile.end(), 0); // Reset notification flags + notify_compile_count = 0; + compile_pending = 0; } worker_index++;