Skip to content

Luau: arming the interrupt from another thread instead of a resident callback #750

Open

Description

@FalkWoldmann

set_interrupt costs a lot with codegen on. Once the pointer in lua_callbacks is non-null, JIT code calls out at every back-edge. In our bench fib(24) goes from 1.04 ms to 2.90 ms with a set_interrupt closure, and to 2.09 ms with a raw C callback that bumps a counter and checks the clock every 128th call. The call-out is the cost, so a throttle inside the closure doesn't help.

In maki we run a watchdog thread that stores a one-shot native interrupt into lua_callbacks(L)->interrupt every 50 ms. The callback clears the pointer, re-checks cancel, deadline and shutdown, and raises if needed. Luau documents that slot as safe to assign from another thread. Fib is back at 1.04 ms, but it's forty lines of unsafe we'd rather not own.

Would you take a PR that adds this to mlua? Maybe set_interrupt returning a Send + Sync handle, with the pointer null until handle.arm() and cleared before the closure runs:

let poke = lua.set_interrupt_oneshot(|_| Err(mlua::Error::runtime("timeout")));
// from a timer thread
poke.arm();

I'm not sure about the shape, happy to go with whatever fits the existing API better

Activity

  1. khvzak commented on Nov 5, 2026

    @khvzak
    Member

    Makes sense, I like this idea.

    I was working on this over the past couple of days and opened a PR #752 with the proposed design/implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions