Skip to content

perf: back say and Http.Status.set with EffectFn1 foreigns - #8

Merged
Unisay merged 1 commit into
mainfrom
issue-186/effectfn-ffi
Jul 13, 2026
Merged

perf: back say and Http.Status.set with EffectFn1 foreigns#8
Unisay merged 1 commit into
mainfrom
issue-186/effectfn-ffi

Conversation

@Unisay

Copy link
Copy Markdown
Collaborator

Problem

say :: String -> Effect Unit and Lua.Ngx.Http.Status.set :: Status -> Effect Unit were curried effect foreigns, so every call paid two Lua calls plus a freshly allocated effect thunk. With the compiler's uncurried lift in place (purescript-lua/purescript-lua#198), an EffectFn1 shape compiles to a single direct call instead. These are exactly the Lua-specific foreigns the #186 audit scoped for conversion (ngx has no upstream to stay API-compatible with, and the public API does not change anyway).

Change

The foreigns become sayImpl/setImpl :: EffectFn1 … with thin public wrappers (say = runEffectFn1 sayImpl), and the .lua entries become 1-ary functions performing the effect directly. get :: Effect Status stays as is: a thunk is already a single call, and there is no EffectFn0. Status constants untouched.

Verification

scripts/build green. Differential link of a probe app (say "hello" *> say "world" *> set ok) against main vs this branch: every call site collapses from Lua_Ngx_say("hello")() (two calls and a closure per invocation) to Lua_Ngx_sayImpl("hello"), one direct call with the effect thunk fused away by magic-do. Both linked outputs were executed under Lua 5.1 with an ngx stub and produce identical behaviour (same say output, same status assignment). No OpenResty runtime smoke: the change surface is the calling convention only.

Suggested release: minor (v0.3.0, since the module surface gains the *Impl exports) plus a package-set bump.

Refs purescript-lua/purescript-lua#186.

The curried String -> Effect Unit FFI shape compiles every call into
two Lua calls plus a fresh effect-thunk closure. Declaring the foreigns
as EffectFn1 (sayImpl, setImpl) behind thin public wrappers keeps the
API unchanged while letting the compiler collapse saturated call sites
into one direct call: M.say("x")() becomes sayImpl("x"). Demonstrated
by a differential link of a probe app against this branch vs main.
Refs purescript-lua/purescript-lua#186.
@Unisay
Unisay merged commit 92e88d8 into mainJul 13, 2026
1 check passed
@Unisay
Unisay deleted the issue-186/effectfn-ffi branch July 13, 2026 13:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Unisay