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.
diff --git a/src/hlua.c b/src/hlua.c
index 37f7866..742acc7 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -905,6 +905,7 @@
 	}
 	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 @@
 	 * 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 @@
 		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 @@
 	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 @@
 	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 @@
 	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);