nupp.profile.zone

Gated LuaJIT profiler zones: the stack work is skipped until a profiler asks for it.

local zone = nupp.profile.zone

local function render(): nil
    zone.push("render")
    drawWorld()
    drawOverlay()
    zone.pop()
end

Stock jit.zone pushes and pops whether or not anything is listening. Skipping that is worth doing, but it is not the main cost: a zone marker is a call inside the code being measured, and calls in a hot path abort traces. Mark warm paths, not the hottest ones.

jit.zone itself is left alone. Replacing its __call with a no-op would silently blank every other user of the one global stack, luajit -jp=z included. The trade is that while a session is held this is the only writer: a direct jit.zone push in that window is overwritten.

acquire and release are counted, so several channels can share one stack. This is process-wide, not per-coroutine.

push and pop are compiler intrinsics: a call in statement position on a receiver statically known to hold this module is generated inline against the fields below, rather than made, with pop's popped name also needing to be discarded. The same call a hot path would otherwise pay for is what the note above is about. The fields exist for that generated code to reach; every other call site, and every function below, still goes through the ordinary API.

See Profiling for what a zone path does to a report, and nupp.profile for the sessions that read one.

Module contents

Functions

FunctionKindDescription
acquirefunctionStarts recording, or joins a recording in progress.
currentfunctionThe innermost zone, without popping it.
depthfunctionHow many zones are pushed.
enterfunctionPushes a zone and answers a token for leave, or 0 when inactive.
isActivefunctionWhether pushes and pops are being recorded.
leavefunctionCloses a zone opened by enter.
pathfunctionThe pushed zones joined with "/", outermost first, or "" when none are.
popfunctionPops the innermost zone, or nil when inactive or empty.
pushfunctionPushes a zone.
releasefunctionReleases one acquire; the last empties the stack.

Functions#

zone.acquirefunction#

function zone.acquire(): nil

Starts recording, or joins a recording in progress. Needs a matching release. The first caller clears the stack and opens a new generation, so tokens from an earlier session cannot pop into this one.

Returns

TypeDescription
nil

zone.currentfunction#

function zone.current(): string?

The innermost zone, without popping it.

Returns

TypeDescription
string?

zone.depthfunction#

function zone.depth(): integer

How many zones are pushed. Zero when inactive.

Returns

TypeDescription
integer

zone.enterfunction#

function zone.enter(name: string): integer

Pushes a zone and answers a token for leave, or 0 when inactive.

The paired form, for a leave that may run after its session ended, usually a coroutine resumed after a profile stopped. The token carries the generation, so a late leave is discarded rather than popping someone else's zone.

local token = zone.enter("request")
local answer = fetch()
zone.leave(token)

Arguments

NameTypeDescription
namestring

what to attribute the work below this to

Returns

TypeDescription
integer

the token leave needs, or 0 when nothing is recording

zone.isActivefunction#

function zone.isActive(): boolean

Whether pushes and pops are being recorded.

Returns

TypeDescription
boolean

zone.leavefunction#

function zone.leave(token: integer): nil

Closes a zone opened by enter. A zero token, a stale generation, or an empty stack are all ignored.

Arguments

NameTypeDescription
tokeninteger

what the matching enter answered

Returns

TypeDescription
nil

zone.pathfunction#

function zone.path(): string

The pushed zones joined with "/", outermost first, or "" when none are.

Cached until the stack next changes, so reading it repeatedly between two pushes costs a comparison. That is worth the two words it takes: a profiler reads this from the sampling callback, on the thread it interrupted, and a string built fresh there is an allocation charged to whatever the program happened to be doing, which the same profiler then reports as collector time the program did not spend.

Returns

TypeDescription
string

zone.popfunction#

function zone.pop(): string?

Pops the innermost zone, or nil when inactive or empty. Empty is not an error: a profile can start or stop part-way through a frame, leaving half a pair outside the session.

Called in statement position on a receiver statically known to be this module, with the popped name discarded, this is generated inline instead. See the module comment.

Returns

TypeDescription
string?

zone.pushfunction#

function zone.push(name: string): nil

Pushes a zone. A no-op while inactive.

Called in statement position on a receiver statically known to be this module, this is generated inline against the fields above rather than called. See the module comment.

zone.push("render/overlay")
drawOverlay()
zone.pop()

Arguments

NameTypeDescription
namestring

what to attribute the work below this to

Returns

TypeDescription
nil

zone.releasefunction#

function zone.release(): nil

Releases one acquire; the last empties the stack. Releasing nothing is ignored, so a teardown that runs twice is harmless.

Returns

TypeDescription
nil