Performance & @jit
-- @jit — bytecode compilation
A pragma line anywhere in the file:
-- @jit
compiles the script (and everything it requires) to JVM bytecode instead of
interpreting it. Hot code gets JIT-compiled by the JVM and runs several times faster —
worth it for heavy logic in tick, frame and render callbacks.
If compilation fails, the script automatically loads interpreted and chat shows
@jit compilation failed, running interpreted — remove the pragma or simplify the
construct the compiler choked on.
Tips
-
Read settings once. Every
setting:get()crosses into Java. In a hot callback, read values into locals at the top.module:event("render_2d", function(render) local argb = color:get() -- once for i = 1, #list do ... end -- not color:get() inside the loop end) -
Collect in
tick, draw in render.world.players()/entities()build snapshot tables — too expensive per frame. Collect once per tick (20/s) and only project and draw inrender_2d.local tracked = {} module:event("tick", function() local list = {} for _, e in ipairs(world.entities()) do if not e.is_self and e.distance < 64 then list[#list + 1] = e end end tracked = list end) module:event("render_2d", function(render) for i = 1, #tracked do local x, y, w, h = projection.entity_box(tracked[i].id) if x then render.outline(x, y, w, h, 0xFF4FF2A6, 0, 1) end end end) -
projection.entity_box(id)instead of rebuilding tables — it projects the live entity by id with interpolation, allocating nothing on the script side. -
Localize hot functions:
local entity_box = projection.entity_boxbefore a loop avoids repeated table lookups. -
Don't subscribe for nothing. A
frame/packet_sendcallback fires very often; if once per tick is enough — usetick. -
Coroutines are expensive — don't create them in a loop.