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()
endStock 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
| Function | Kind | Description |
|---|---|---|
acquire | function | Starts recording, or joins a recording in progress. |
current | function | The innermost zone, without popping it. |
depth | function | How many zones are pushed. |
enter | function | Pushes a zone and answers a token for leave, or 0 when inactive. |
isActive | function | Whether pushes and pops are being recorded. |
leave | function | Closes a zone opened by enter. |
path | function | The pushed zones joined with "/", outermost first, or "" when none are. |
pop | function | Pops the innermost zone, or nil when inactive or empty. |
push | function | Pushes a zone. |
release | function | Releases one acquire; the last empties the stack. |
Functions#
zone.acquirefunction#
function zone.acquire(): nilStarts 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
| Type | Description |
|---|---|
nil |
zone.currentfunction#
function zone.current(): string?The innermost zone, without popping it.
Returns
| Type | Description |
|---|---|
string? |
zone.depthfunction#
function zone.depth(): integerHow many zones are pushed. Zero when inactive.
Returns
| Type | Description |
|---|---|
integer |
zone.enterfunction#
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.
Arguments
| Name | Type | Description |
|---|---|---|
name | string | what to attribute the work below this to |
Returns
| Type | Description |
|---|---|
integer | the token |
zone.isActivefunction#
function zone.isActive(): booleanWhether pushes and pops are being recorded.
Returns
| Type | Description |
|---|---|
boolean |
zone.leavefunction#
function zone.leave(token: integer): nilCloses a zone opened by enter. A zero token, a stale generation, or an empty stack are all ignored.
Arguments
| Name | Type | Description |
|---|---|---|
token | integer | what the matching |
Returns
| Type | Description |
|---|---|
nil |
zone.pathfunction#
function zone.path(): stringThe 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
| Type | Description |
|---|---|
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
| Type | Description |
|---|---|
string? |
zone.pushfunction#
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.
Arguments
| Name | Type | Description |
|---|---|---|
name | string | what to attribute the work below this to |
Returns
| Type | Description |
|---|---|
nil |
zone.releasefunction#
function zone.release(): nilReleases one acquire; the last empties the stack. Releasing nothing is ignored, so a teardown that runs twice is harmless.
Returns
| Type | Description |
|---|---|
nil |