[master] 25349b1ac manage dynamic privs as a red/black tree

Nils Goroll nils.goroll at uplex.de
Mon Nov 5 17:16:12 UTC 2018


commit 25349b1ac78e8eed1e2da98ed941ad058232019b
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Tue Oct 30 18:49:18 2018 +0100

    manage dynamic privs as a red/black tree
    
    O(n) does not scale for a high number of dynamic privs, so trade some
    workspace for O(lg n)

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index ce39e683d..2b13aa9ce 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -49,6 +49,7 @@
 #include "miniobj.h"
 #include "vas.h"
 #include "vqueue.h"
+#include "vtree.h"
 
 #include "vapi/vsl_int.h"
 
@@ -198,10 +199,12 @@ struct vxid_pool {
 
 /*--------------------------------------------------------------------*/
 
+VRBT_HEAD(vrt_priv_tree,vrt_priv);
+
 struct vrt_privs {
 	unsigned		magic;
-#define VRT_PRIVS_MAGIC		0x03ba7501
-	VTAILQ_HEAD(,vrt_priv)	privs;
+#define VRT_PRIVS_MAGIC		0x03ba7502
+	struct vrt_priv_tree	privs;
 };
 
 /* Worker pool stuff -------------------------------------------------*/
diff --git a/bin/varnishd/cache/cache_vrt_priv.c b/bin/varnishd/cache/cache_vrt_priv.c
index 6b3b455fe..704a6f7a6 100644
--- a/bin/varnishd/cache/cache_vrt_priv.c
+++ b/bin/varnishd/cache/cache_vrt_priv.c
@@ -40,7 +40,7 @@
 struct vrt_priv {
 	unsigned			magic;
 #define VRT_PRIV_MAGIC			0x24157a52
-	VTAILQ_ENTRY(vrt_priv)		list;
+	VRBT_ENTRY(vrt_priv)		entry;
 	struct vmod_priv		priv[1];
 	const struct vcl		*vcl;
 	uintptr_t			id;	// = scope / vrt_privs
@@ -49,6 +49,10 @@ struct vrt_priv {
 
 struct vrt_privs cli_task_privs[1];
 
+static inline int vrt_priv_dyncmp(const struct vrt_priv *,
+    const struct vrt_priv *);
+VRBT_PROTOTYPE(vrt_priv_tree, vrt_priv, entry, vrt_priv_dyncmp);
+
 /*--------------------------------------------------------------------
  */
 
@@ -63,7 +67,7 @@ pan_privs(struct vsb *vsb, const struct vrt_privs *privs)
 	VSB_indent(vsb, 2);
 	PAN_CheckMagic(vsb, privs, VRT_PRIVS_MAGIC);
 	if (privs->magic == VRT_PRIVS_MAGIC) {
-		VTAILQ_FOREACH(vp, &privs->privs, list) {
+		VRBT_FOREACH(vp, vrt_priv_tree, &privs->privs) {
 			PAN_CheckMagic(vsb, vp, VRT_PRIV_MAGIC);
 			VSB_printf(vsb,
 			    "priv {p %p l %d f %p} vcl %p id %jx vmod %jx\n",
@@ -89,26 +93,40 @@ VRTPRIV_init(struct vrt_privs *privs)
 {
 
 	INIT_OBJ(privs, VRT_PRIVS_MAGIC);
-	VTAILQ_INIT(&privs->privs);
+	VRBT_INIT(&privs->privs);
+}
+
+static inline int
+vrt_priv_dyncmp(const struct vrt_priv *vp1, const struct vrt_priv *vp2)
+{
+	if (vp1->vmod_id < vp2->vmod_id)
+		return (-1);
+	if (vp1->vmod_id > vp2->vmod_id)
+		return (1);
+	return (0);
 }
 
+VRBT_GENERATE(vrt_priv_tree, vrt_priv, entry, vrt_priv_dyncmp);
+
 static struct vmod_priv *
 vrt_priv_dynamic(const struct vcl *vcl, struct ws *ws,
      struct vrt_privs *vps, uintptr_t id, uintptr_t vmod_id)
 {
 	struct vrt_priv *vp;
+	const struct vrt_priv needle = {.vmod_id = vmod_id};
 
 	CHECK_OBJ_NOTNULL(vps, VRT_PRIVS_MAGIC);
 	AN(vmod_id);
 
-	VTAILQ_FOREACH(vp, &vps->privs, list) {
-		CHECK_OBJ_NOTNULL(vp, VRT_PRIV_MAGIC);
-		if (vp->vmod_id == vmod_id) {
-			assert(vp->vcl == vcl);
-			assert(vp->id == id);
-			return (vp->priv);
-		}
+	vp = VRBT_FIND(vrt_priv_tree, &vps->privs, &needle);
+	if (vp) {
+		CHECK_OBJ(vp, VRT_PRIV_MAGIC);
+		assert(vp->vmod_id == vmod_id);
+		assert(vp->vcl == vcl);
+		assert(vp->id == id);
+		return (vp->priv);
 	}
+
 	vp = WS_Alloc(ws, sizeof *vp);
 	if (vp == NULL)
 		return (NULL);
@@ -116,7 +134,7 @@ vrt_priv_dynamic(const struct vcl *vcl, struct ws *ws,
 	vp->vcl = vcl;
 	vp->id = id;
 	vp->vmod_id = vmod_id;
-	VTAILQ_INSERT_TAIL(&vps->privs, vp, list);
+	VRBT_INSERT(vrt_priv_tree, &vps->privs, vp);
 	return (vp->priv);
 }
 
@@ -197,10 +215,8 @@ VCL_TaskLeave(const struct vcl *vcl, struct vrt_privs *privs)
 
 	AN(vcl);
 	CHECK_OBJ_NOTNULL(privs, VRT_PRIVS_MAGIC);
-	VTAILQ_FOREACH_SAFE(vp, &privs->privs, list, vp1) {
-		VTAILQ_REMOVE(&privs->privs, vp, list);
+	VRBT_FOREACH_SAFE(vp, vrt_priv_tree, &privs->privs, vp1) {
 		VRT_priv_fini(vp->priv);
 	}
 	INIT_OBJ(privs, 0);
 }
-


More information about the varnish-commit mailing list