]> git.ipfire.org Git - thirdparty/haproxy.git/commit
MEDIUM: init/threads: don't use spinlocks during the init phase
authorWilly Tarreau <w@1wt.eu>
Tue, 11 Jun 2019 07:16:41 +0000 (09:16 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 11 Jun 2019 09:30:26 +0000 (11:30 +0200)
commit34a150ccf5157a04558d5b67e3901045d99ccdea
treebf7288f3961c6bc9d38b92bd2ac52a438dbb3d02
parentb5ecf0393cb8636bd838384f254a62f86839df17
MEDIUM: init/threads: don't use spinlocks during the init phase

PiBa-NL found some pathological cases where starting threads can hinder
each other and cause a measurable slow down. This problem is reproducible
with the following config (haproxy must be built with -DDEBUG_DEV) :

    global
stats socket /tmp/sock1 mode 666 level admin
nbthread 64

    backend stopme
timeout server  1s
option tcp-check
tcp-check send "debug dev exit\n"
server cli unix@/tmp/sock1 check

This will cause the process to be stopped once the checks are ready to
start. Binding all these to just a few cores magnifies the problem.
Starting them in loops shows a significant time difference among the
commits :

  # before startup serialization
  $ time for i in {1..20}; do taskset -c 0,1,2,3 ./haproxy-e186161 -db -f slow-init.cfg >/dev/null 2>&1; done

  real    0m1.581s
  user    0m0.621s
  sys     0m5.339s

  # after startup serialization
  $ time for i in {1..20}; do taskset -c 0,1,2,3 ./haproxy-e4d7c9dd -db -f slow-init.cfg >/dev/null 2>&1; done

  real    0m2.366s
  user    0m0.894s
  sys     0m8.238s

In order to address this, let's use plain mutexes and cond_wait during
the init phase. With this done, waiting threads now sleep and the problem
completely disappeared :

  $ time for i in {1..20}; do taskset -c 0,1,2,3 ./haproxy -db -f slow-init.cfg >/dev/null 2>&1; done

  real    0m0.161s
  user    0m0.079s
  sys     0m0.149s
src/haproxy.c