From 0080ee69d552c8c50a16c0aaafe2ab97b97c7c7e Mon Sep 17 00:00:00 2001 From: Nadav Har'El Date: Thu, 18 Jul 2013 08:00:27 +0300 Subject: [PATCH] Micro-benchmark for waking condvar on which no-one is waiting This patch adds to tst-condvar two benchmark for measuring condvar::wake_all() on a condvar that nobody is waiting on. The first benchmark does these wakes from a single thread, measuring 26ns before commit 3509b19bb5c7acc5d97559a44e66e007133b647b, and only 3ns after it. The second benchmark does wake_all() loops from two threads on two different CPUs. Before the aforementioned commit, this frequently involved a contented mutex and context switches, with as much as 30,000 ns delay. After that commit, this benchmark measures 3ns, the same as the single-threaded benchmark. --- tests/tst-condvar.cc | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/tst-condvar.cc b/tests/tst-condvar.cc index 42d7064df6..677922055a 100644 --- a/tests/tst-condvar.cc +++ b/tests/tst-condvar.cc @@ -1,5 +1,8 @@ +#include + #include "sched.hh" #include "debug.hh" +#include #include @@ -131,6 +134,41 @@ int main(int argc, char **argv) } assert_idle(&cond); + debug("Measuring unwaited wake_all (one thread): "); + int iterations = 100000000; + condvar cv; + auto start = nanotime(); + for (int i = 0; i < iterations; i++) { + cv.wake_all(); + } + auto end = nanotime(); + debug ("%d ns\n", (end-start)/iterations); + + + debug("Measuring unwaited wake_all (two threads): "); + iterations = 100000000; + unsigned int nthreads = 2; + assert(sched::cpus.size() >= nthreads); + sched::thread *threads2[nthreads]; + std::atomic time(0); + for(unsigned int i = 0; i < nthreads; i++) { + threads2[i]= new sched::thread([iterations, &cv, &time] { + auto start = nanotime(); + for (int j = 0; j < iterations; j++) { + cv.wake_all(); + } + auto end = nanotime(); + time += (end-start); + }, sched::thread::attr(sched::cpus[i])); + threads2[i]->start(); + } + for(unsigned int i = 0; i < nthreads; i++) { + threads2[i]->join(); + delete threads2[i]; + } + debug ("%d ns\n", time/iterations/nthreads); + + debug("condvar tests succeeded\n"); return 0; }