Skip to main content

LoaderScheduler

Budgets the synchronous work the loader does while walking the package tree.

Bootstrapping recurses over every folder, module script and value in the tree in one go, which on a large game can exhaust Roblox's script execution timeout. Callers thread a scheduler through that recursion and call LoaderScheduler.YieldIfNeededAsync as they walk, which spreads the work over frames instead of blowing the whole budget at once.

Functions

new

LoaderScheduler.new(
labelstring,--

Names the walk being budgeted, for debug output

budgetBeforeYieldnumber?--

Seconds of work allowed before yielding

) → LoaderScheduler

Constructs a new scheduler with a fresh budget.

isLoaderScheduler

LoaderScheduler.isLoaderScheduler(loaderSchedulerany?) → boolean

Returns true if the argument is a loader scheduler

RestartBudget

LoaderScheduler.RestartBudget(
startTimenumber?--

Defaults to now

) → ()

Starts the budget over without yielding. Use this when the caller has already yielded for its own reasons.

Pass a start time from LoaderScheduler.GetBudgetStartTime to continue a window another scheduler already opened, so work handed between schedulers inside one frame keeps counting against that frame instead of each walk being handed a full budget.

GetBudgetStartTime

LoaderScheduler.GetBudgetStartTime(selfLoaderScheduler) → number?

When the current budget window started, or nil if none is open.

ClearBudget

LoaderScheduler.ClearBudget(selfLoaderScheduler) → ()

Clears the budget so the next LoaderScheduler.YieldIfNeededAsync starts a fresh window. Use this when the walk is done, otherwise the next caller measures against however long ago we last yielded.

GetTotalComputeTime

LoaderScheduler.GetTotalComputeTime(selfLoaderScheduler) → number

Total time spent computing, excluding time spent yielded. Compare against wall clock time to see what the yielding is costing.

YieldIfNeededAsync

LoaderScheduler.YieldIfNeededAsync(selfLoaderScheduler) → boolean--

true if we yielded

Yields if this frame's budget is spent, otherwise returns immediately.

Callers that yield here have to revalidate whatever they captured before the call, since the tree can change while we're yielded.

Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Constructs a new scheduler with a fresh budget.",
            "params": [
                {
                    "name": "label",
                    "desc": "Names the walk being budgeted, for debug output",
                    "lua_type": "string"
                },
                {
                    "name": "budgetBeforeYield",
                    "desc": "Seconds of work allowed before yielding",
                    "lua_type": "number?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "LoaderScheduler"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 39,
                "path": "src/loader/src/Timing/LoaderScheduler.lua"
            }
        },
        {
            "name": "isLoaderScheduler",
            "desc": "Returns true if the argument is a loader scheduler",
            "params": [
                {
                    "name": "loaderScheduler",
                    "desc": "",
                    "lua_type": "any?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 60,
                "path": "src/loader/src/Timing/LoaderScheduler.lua"
            }
        },
        {
            "name": "RestartBudget",
            "desc": "Starts the budget over without yielding. Use this when the caller has\nalready yielded for its own reasons.\n\nPass a start time from [LoaderScheduler.GetBudgetStartTime] to continue a\nwindow another scheduler already opened, so work handed between schedulers\ninside one frame keeps counting against that frame instead of each walk\nbeing handed a full budget.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "LoaderScheduler"
                },
                {
                    "name": "startTime",
                    "desc": "Defaults to now",
                    "lua_type": "number?"
                }
            ],
            "returns": [],
            "function_type": "static",
            "source": {
                "line": 75,
                "path": "src/loader/src/Timing/LoaderScheduler.lua"
            }
        },
        {
            "name": "GetBudgetStartTime",
            "desc": "When the current budget window started, or nil if none is open.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "LoaderScheduler"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "number?"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 86,
                "path": "src/loader/src/Timing/LoaderScheduler.lua"
            }
        },
        {
            "name": "ClearBudget",
            "desc": "Clears the budget so the next [LoaderScheduler.YieldIfNeededAsync] starts a\nfresh window. Use this when the walk is done, otherwise the next caller\nmeasures against however long ago we last yielded.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "LoaderScheduler"
                }
            ],
            "returns": [],
            "function_type": "static",
            "source": {
                "line": 95,
                "path": "src/loader/src/Timing/LoaderScheduler.lua"
            }
        },
        {
            "name": "GetTotalComputeTime",
            "desc": "Total time spent computing, excluding time spent yielded. Compare against\nwall clock time to see what the yielding is costing.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "LoaderScheduler"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "number"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 105,
                "path": "src/loader/src/Timing/LoaderScheduler.lua"
            }
        },
        {
            "name": "YieldIfNeededAsync",
            "desc": "Yields if this frame's budget is spent, otherwise returns immediately.\n\nCallers that yield here have to revalidate whatever they captured before\nthe call, since the tree can change while we're yielded.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "LoaderScheduler"
                }
            ],
            "returns": [
                {
                    "desc": "true if we yielded",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 121,
                "path": "src/loader/src/Timing/LoaderScheduler.lua"
            }
        }
    ],
    "properties": [],
    "types": [],
    "name": "LoaderScheduler",
    "desc": "Budgets the synchronous work the loader does while walking the package tree.\n\nBootstrapping recurses over every folder, module script and value in the\ntree in one go, which on a large game can exhaust Roblox's script execution\ntimeout. Callers thread a scheduler through that recursion and call\n[LoaderScheduler.YieldIfNeededAsync] as they walk, which spreads the work over\nframes instead of blowing the whole budget at once.",
    "source": {
        "line": 13,
        "path": "src/loader/src/Timing/LoaderScheduler.lua"
    }
}