]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
OPTIM: peers: avoid the locking dance around peer_send_teach_process_msgs()
authorWilly Tarreau <w@1wt.eu>
Tue, 2 Apr 2024 16:27:36 +0000 (18:27 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 3 Apr 2024 07:34:08 +0000 (09:34 +0200)
In peer_send_msg(), we take a lock before calling
peer_send_teach_process_msgs because of the check on the flags and update
indexes, and the function then drops it then takes it again just to resume
in the same situation, so that on return we can drop it again! Not only
this is absurd because it doubles the costs of taking the lock, it's also
totally inefficient because it takes a write lock while the only usage
that is done with it is to read the indexes! Let's drop the lock from
peer_send_teach_process_msgs() and move it explicitly in its only caller
around the condition, and turn it into a read lock only.

src/peers.c

index 272445929cab2331e99c259da8ed4ce473ef5cc6..628b9358c61bbde2a46ba85dc3d722aac34d4c11 100644 (file)
@@ -1651,13 +1651,7 @@ static inline int peer_send_teachmsgs(struct appctx *appctx, struct peer *p,
 static inline int peer_send_teach_process_msgs(struct appctx *appctx, struct peer *p,
                                                struct shared_table *st)
 {
-       int ret;
-
-       HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->updt_lock);
-       ret = peer_send_teachmsgs(appctx, p, peer_teach_process_stksess_lookup, st);
-       HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->updt_lock);
-
-       return ret;
+       return peer_send_teachmsgs(appctx, p, peer_teach_process_stksess_lookup, st);
 }
 
 /*
@@ -2689,18 +2683,19 @@ static inline int peer_send_msgs(struct appctx *appctx,
                        }
 
                        if (!(peer->flags & PEER_F_TEACH_PROCESS)) {
-                               HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->updt_lock);
-                               if (!(peer->flags & PEER_F_LEARN_ASSIGN) &&
-                                       (st->last_pushed != st->table->localupdate)) {
+                               int must_send;
+
+                               HA_RWLOCK_RDLOCK(STK_TABLE_LOCK, &st->table->updt_lock);
+                               must_send = !(peer->flags & PEER_F_LEARN_ASSIGN) && (st->last_pushed != st->table->localupdate);
+                               HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &st->table->updt_lock);
 
+                               if (must_send) {
                                        repl = peer_send_teach_process_msgs(appctx, peer, st);
                                        if (repl <= 0) {
-                                               HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->updt_lock);
                                                peer->stop_local_table = peer->last_local_table;
                                                return repl;
                                        }
                                }
-                               HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->updt_lock);
                        }
                        else if (!(peer->flags & PEER_F_TEACH_FINISHED)) {
                                if (!(st->flags & SHTABLE_F_TEACH_STAGE1)) {