fix(rbxl): watchdog 100k→20k + откат pcall(yield) + batch 5+20ms
Прошлый коммит pcall(coroutine.yield) дал бесконечный цикл: yield внутри C-call падал → pcall ловил → hook возвращался → счётчик не сбросился → срабатывал опять моментально → вис. Новая стратегия: 1. Голый coroutine.yield в watchdog: если внутри C-call упадёт с ошибкой — pcall(fn,...) внутри coroutine её поймает, скрипт завершится. Лучше чем вис. 2. Frequency 100k→20k инструкций — yield чаще, меньше времени на tight-loop перед уступкой управления UI. 3. Batch kickoff 20→5 скриптов с delay 20мс (было 0). 55 скриптов ROBLOX Battle = ~200мс распределено, UI отзывается. Page-hang при init должен исчезнуть. Скрипты с tight-loop типа WaitForChild через ChildAdded:wait() упадут с ошибкой про yield, но не повесят страницу.
This commit is contained in:
parent
734521df72
commit
38d135586b
@ -115,8 +115,8 @@ export class LuaSharedSandbox {
|
||||
// Запускаем main-loop сразу — он начнёт tick'ать как только будут coroutines.
|
||||
this._lastTickAt = performance.now();
|
||||
this._startMainLoop();
|
||||
// Init батчами по 20 с yield между ними, чтобы UI не подвисал на 700+ скриптах.
|
||||
const BATCH_SIZE = 20;
|
||||
// Init батчами по 5 с задержкой 20мс между ними, чтобы UI отзывался.
|
||||
const BATCH_SIZE = 5;
|
||||
let idx = 0;
|
||||
const initBatch = () => {
|
||||
if (this._isStopped) return;
|
||||
@ -130,7 +130,7 @@ export class LuaSharedSandbox {
|
||||
}
|
||||
idx = end;
|
||||
if (idx < pending.length) {
|
||||
setTimeout(initBatch, 0);
|
||||
setTimeout(initBatch, 20);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`[LuaSharedSandbox] all ${pending.length} scripts kicked off`);
|
||||
@ -199,13 +199,11 @@ export class LuaSharedSandbox {
|
||||
})
|
||||
local co = coroutine.create(function()
|
||||
-- WATCHDOG: каждые 100000 инструкций — yield 1 кадр.
|
||||
-- Защищает от tight-loop. yield обёрнут в pcall так как
|
||||
-- внутри C-call boundary yield бросает ошибку — но в этом
|
||||
-- случае tight-loop наш hook просто будет вызываться позже
|
||||
-- (когда Lua вернётся из C-call) и yield сработает.
|
||||
-- НЕ оборачиваем в pcall — внутри C-call boundary yield
|
||||
-- упадёт ошибкой, что прервёт скрипт. Это лучше чем виснуть.
|
||||
debug.sethook(function()
|
||||
pcall(coroutine.yield, 0.016)
|
||||
end, "", 100000)
|
||||
coroutine.yield(0.016)
|
||||
end, "", 20000)
|
||||
-- pcall защищает от runtime-ошибок которые иначе крашат
|
||||
-- coroutine и могут повредить WASM-стейт. Возвраты
|
||||
-- handler'а намеренно поглощаются.
|
||||
|
||||
@ -1642,11 +1642,9 @@ export function registerRobloxShim(lua, opts) {
|
||||
-- (ok, ret1, ret2, ...) — мы их не используем.
|
||||
local co = coroutine.create(function()
|
||||
-- Тот же watchdog что и в _startSingleScript.
|
||||
-- yield обёрнут в pcall: внутри C-call boundary yield бросает
|
||||
-- ошибку, но hook будет вызван позже когда Lua вернётся.
|
||||
debug.sethook(function()
|
||||
pcall(coroutine.yield, 0.016)
|
||||
end, "", 100000)
|
||||
coroutine.yield(0.016)
|
||||
end, "", 20000)
|
||||
pcall(fn, a1, a2, a3, a4)
|
||||
end)
|
||||
__rbxl_register_coroutine(handlerId, co)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user