]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lua FFI: avoid frequent usage of lua_pushpointer()
authorVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 7 Aug 2019 07:36:13 +0000 (09:36 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 28 Nov 2019 12:05:05 +0000 (13:05 +0100)
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.

daemon/ffimodule.c
daemon/ffimodule.h
daemon/lua/kres-gen.lua
daemon/lua/kres-gen.sh
daemon/lua/sandbox.lua.in

index 24f6aaccdc29a278b728b147e28fe87d6537befa..c1cb50e9880890524f3011c7eed3ad0241ce272a 100644 (file)
@@ -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;
 }
index 564fa991b890270d384e0ef0217a14e9647d727a..81f5425d6e1cd64307149d261c810a490708b6b9 100644 (file)
 
 #pragma once
 
+#include "lib/defines.h"
+#include "lib/layer.h"
+#include <lua.h>
+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;
+
index ed48d753e5563322650a83ef7578c5859cd140fb..e59294bb7302a01476dfd2a96f4d66e40edcc545 100644 (file)
@@ -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);
 
index fd16e492ce5f2504870b4ed3ea85525ab4278fc5..c56ced70669bfd5e3098d52bda312b9f11d5bf89 100755 (executable)
@@ -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);
index b3b9394727b45741ad08bf286917216151dfc0ef..d31fcf02c102d799b2832d7764a8ccc62382f4d2 100644 (file)
@@ -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]