From: Vladimír Čunát Date: Wed, 7 Aug 2019 07:36:13 +0000 (+0200) Subject: lua FFI: avoid frequent usage of lua_pushpointer() X-Git-Tag: v4.3.0~4^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3647106a9c45a115477bd8a1060edcbc687f8da4;p=thirdparty%2Fknot-resolver.git lua FFI: avoid frequent usage of lua_pushpointer() The new way of transitioning to layer callbacks - done because of portability (mainly to aarch64) - is a bit expensive. This is a simple way of recovering that cost. Merge 603a24f regressed speed a bit. --- diff --git a/daemon/ffimodule.c b/daemon/ffimodule.c index 24f6aaccd..c1cb50e98 100644 --- a/daemon/ffimodule.c +++ b/daemon/ffimodule.c @@ -126,6 +126,8 @@ static int l_ffi_deinit(struct kr_module *module) return ret; } +kr_layer_t kr_layer_t_static; + /** @internal Helper for calling a layer Lua function by e.g. SLOT_begin. */ static int l_ffi_call_layer(kr_layer_t *ctx, int slot_ix) { @@ -135,8 +137,11 @@ static int l_ffi_call_layer(kr_layer_t *ctx, int slot_ix) lua_State *L = the_worker->engine->L; lua_rawgeti(L, LUA_REGISTRYINDEX, wrap_slot); lua_rawgeti(L, LUA_REGISTRYINDEX, cb_slot); - lua_pushpointer(L, ctx); - const int ret = l_ffi_call_mod(L, 2); + /* We pass the content of *ctx via a global structure to avoid + * lua (full) userdata, as that's relatively expensive (GC-allocated). + * Performance: copying isn't ideal, but it's not visible in profiles. */ + memcpy(&kr_layer_t_static, ctx, sizeof(*ctx)); + const int ret = l_ffi_call_mod(L, 1); /* The return codes are mixed at this point. We need to return KR_STATE_* */ return ret < 0 ? KR_STATE_FAIL : ret; } diff --git a/daemon/ffimodule.h b/daemon/ffimodule.h index 564fa991b..81f5425d6 100644 --- a/daemon/ffimodule.h +++ b/daemon/ffimodule.h @@ -16,6 +16,12 @@ #pragma once +#include "lib/defines.h" +#include "lib/layer.h" +#include +struct engine; +struct kr_module; + /** * Register Lua module as a FFI module. * This fabricates a standard module interface, @@ -35,3 +41,8 @@ int ffimodule_register_lua(struct engine *engine, struct kr_module *module, cons int ffimodule_init(lua_State *L); void ffimodule_deinit(lua_State *L); +/** Static storage for faster passing of layer function parameters to lua callbacks. + * + * We don't need to declare it in a header, but let's give it visibility. */ +KR_EXPORT kr_layer_t kr_layer_t_static; + diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua index ed48d753e..e59294bb7 100644 --- a/daemon/lua/kres-gen.lua +++ b/daemon/lua/kres-gen.lua @@ -251,7 +251,7 @@ struct kr_module { void *lib; void *data; }; - +kr_layer_t kr_layer_t_static; typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type, const struct kr_query *qry); diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh index fd16e492c..c56ced706 100755 --- a/daemon/lua/kres-gen.sh +++ b/daemon/lua/kres-gen.sh @@ -124,6 +124,9 @@ ${CDEFS} ${LIBKRES} types <<-EOF struct kr_module EOF +# a static variable; the line might not be simple to generate +printf "kr_layer_t kr_layer_t_static;" + printf " typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type, const struct kr_query *qry); diff --git a/daemon/lua/sandbox.lua.in b/daemon/lua/sandbox.lua.in index b3b939472..d31fcf02c 100644 --- a/daemon/lua/sandbox.lua.in +++ b/daemon/lua/sandbox.lua.in @@ -262,18 +262,17 @@ function modules_create_table_for_c(kr_module_ud) }) end +local layer_ctx = ffi.C.kr_layer_t_static -- Utilities internal for lua layer glue; see ../ffimodule.c -modules_ffi_layer_wrap1 = function (layer_cb, ctx_udata) - local ctx = ffi.cast('kr_layer_t **', ctx_udata)[0] - return layer_cb(ctx.state, ctx.req) +modules_ffi_layer_wrap1 = function (layer_cb) + return layer_cb(layer_ctx.state, layer_ctx.req) end -modules_ffi_layer_wrap2 = function (layer_cb, ctx_udata) - local ctx = ffi.cast('kr_layer_t **', ctx_udata)[0] - return layer_cb(ctx.state, ctx.req, ctx.pkt) +modules_ffi_layer_wrap2 = function (layer_cb) + return layer_cb(layer_ctx.state, layer_ctx.req, layer_ctx.pkt) end -modules_ffi_layer_wrap_checkout = function (layer_cb, ctx_udata) - local ctx = ffi.cast('kr_layer_t **', ctx_udata)[0] - return layer_cb(ctx.state, ctx.req, ctx.pkt, ctx.dst, ctx.is_stream) +modules_ffi_layer_wrap_checkout = function (layer_cb) + return layer_cb(layer_ctx.state, layer_ctx.req, layer_ctx.pkt, + layer_ctx.dst, layer_ctx.is_stream) end modules_ffi_wrap_modcb = function (cb, kr_module_ud) -- this one isn't for layer local kr_module = ffi.cast('struct kr_module **', kr_module_ud)[0]