MEDIUM: lua: don't call the GC as often when dealing with outgoing connections
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.
This commit is contained in:
parent
9a8ef7f51d
commit
f31af9367e
|
@ -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
|
||||
|
|
13
src/hlua.c
13
src/hlua.c
|
@ -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 @@ static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue