]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: lua: don't call the GC as often when dealing with outgoing connections
authorWilly Tarreau <w@1wt.eu>
Tue, 14 Jan 2020 08:59:38 +0000 (09:59 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 14 Jan 2020 09:12:31 +0000 (10:12 +0100)
In order to properly close connections established from Lua in case
a Lua context dies, the context currently automatically gets a flag
HLUA_MUST_GC set whenever an outgoing connection is used. This causes
the GC to be enforced on the context's death as well as on yield. First,
it does not appear necessary to do it when yielding, since if the
connections die they are already cleaned up. Second, the problem with
the flag is that even if a connection gets properly closed, the flag is
not removed and the GC continues to be called on the Lua context.

The impact on performance looks quite significant, as noticed and
diagnosed by Sadasiva Gujjarlapudi in the following thread:

  https://www.mail-archive.com/haproxy@formilux.org/msg35810.html

This patch changes the flag for a counter so that each created
connection increments it and each cleanly closed connection decrements
it. That way we know we have to call the GC on the context's death only
if the count is non-null. As reported in the thread above, the Lua
performance gain is now over 20% by doing this.

Thanks to Sada and Thierry for the design discussion and tests that
led to this solution.

include/types/hlua.h
src/hlua.c

index fb1796c7f35a3c5588b47548b9be187cabcdc08a..6febee233cdd4cc52204105c8859430b7961bd49 100644 (file)
@@ -37,7 +37,7 @@ struct stream;
 #define HLUA_WAKERESWR 0x00000004
 #define HLUA_WAKEREQWR 0x00000008
 #define HLUA_EXIT      0x00000010
-#define HLUA_MUST_GC   0x00000020
+/* unused:   0x00000020 */
 #define HLUA_STOP      0x00000040
 
 #define HLUA_F_AS_STRING    0x01
@@ -93,6 +93,7 @@ struct hlua {
        struct list com; /* The list head of the signals attached to this task. */
        struct ebpt_node node;
        struct hlua_consistency cons; /* Store data consistency check. */
+       int gc_count;  /* number of items which need a GC */
 };
 
 /* This is a part of the list containing references to functions
index 37f7866874a2e25df43727df42fce6898ee7e36f..742acc7062b77df62cdef5851c14c7ed2c9b6bdf 100644 (file)
@@ -905,6 +905,7 @@ int hlua_ctx_init(struct hlua *lua, struct task *task, int already_safe)
        }
        lua->Mref = LUA_REFNIL;
        lua->flags = 0;
+       lua->gc_count = 0;
        LIST_INIT(&lua->com);
        lua->T = lua_newthread(gL.T);
        if (!lua->T) {
@@ -954,7 +955,7 @@ void hlua_ctx_destroy(struct hlua *lua)
         * NOTE: maybe this action locks all the Lua threads untiml the en of
         * the garbage collection.
         */
-       if (lua->flags & HLUA_MUST_GC) {
+       if (lua->gc_count) {
                if (!SET_SAFE_LJMP(gL.T))
                        return;
                lua_gc(gL.T, LUA_GCCOLLECT, 0);
@@ -1194,11 +1195,6 @@ resume_execution:
                break;
        }
 
-       /* This GC permits to destroy some object when a Lua timeout strikes. */
-       if (lua->flags & HLUA_MUST_GC &&
-           ret != HLUA_E_AGAIN)
-               lua_gc(lua->T, LUA_GCCOLLECT, 0);
-
        switch (ret) {
        case HLUA_E_AGAIN:
                break;
@@ -1699,6 +1695,7 @@ __LJMP static int hlua_socket_close_helper(lua_State *L)
        struct hlua_socket *socket;
        struct appctx *appctx;
        struct xref *peer;
+       struct hlua *hlua = hlua_gethlua(L);
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
 
@@ -1711,6 +1708,8 @@ __LJMP static int hlua_socket_close_helper(lua_State *L)
        peer = xref_get_peer_and_lock(&socket->xref);
        if (!peer)
                return 0;
+
+       hlua->gc_count--;
        appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
 
        /* Set the flag which destroy the session. */
@@ -2463,7 +2462,7 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
        si_rx_endp_more(&s->si[0]);
        appctx_wakeup(appctx);
 
-       hlua->flags |= HLUA_MUST_GC;
+       hlua->gc_count++;
 
        if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
                xref_unlock(&socket->xref, peer);