From ff256d9e57aac1563c999ae7a6b4df7016e8418c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 24 Mar 2018 09:03:14 +0100 Subject: [PATCH] DI: benchmark naive lock protected access ...which gives us the dramatic numbers we'd expect. Especially the multithreaded variant contends drastically --- research/try.cpp | 4 ++-- src/lib/depend-inject.hpp | 12 ++++++------ src/lib/depend2.hpp | 4 +++- wiki/renderengine.html | 1 + 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/research/try.cpp b/research/try.cpp index ad18b04e0..7c724a77a 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -102,11 +102,11 @@ main (int, char**) Depend mystery; - cout << microbenchmark<8> ([&]() + cout << microbenchmark<1> ([&]() { 0 == mystery().readMe(); } - ,200000000) + ,50000000) << endl; LifecycleHook::trigger (ON_GLOBAL_SHUTDOWN); diff --git a/src/lib/depend-inject.hpp b/src/lib/depend-inject.hpp index 47589cee6..0fdbff206 100644 --- a/src/lib/depend-inject.hpp +++ b/src/lib/depend-inject.hpp @@ -74,7 +74,7 @@ namespace lib { struct DependInject { using Factory = typename Depend::Factory; - + using Lock = typename Depend::Lock; /** configure dependency-injection for type SRV to build a subclass singleton * @tparam SUB concrete subclass type to build on demand when invoking `Depend` @@ -259,7 +259,7 @@ namespace lib { static void installFactory (Factory&& otherFac) { - ClassLock guard; + Lock guard; if (Depend::instance) throw error::Logic("Attempt to reconfigure dependency injection after the fact. " "The previously installed factory (typically Singleton) was already used." @@ -270,7 +270,7 @@ namespace lib { static void temporarilyInstallAlternateFactory (SRV*& stashInstance, Factory& stashFac, Factory&& newFac) { - ClassLock guard; + Lock guard; stashFac = move(Depend::factory); stashInstance = Depend::instance; Depend::factory = move(newFac); @@ -280,7 +280,7 @@ namespace lib { static void restoreOriginalFactory (SRV*& stashInstance, Factory& stashFac) { - ClassLock guard; + Lock guard; Depend::factory = move(stashFac); Depend::instance = stashInstance; } @@ -288,7 +288,7 @@ namespace lib { static void activateServiceAccess (SRV& newInstance) { - ClassLock guard; + Lock guard; if (Depend::instance) throw error::Logic("Attempt to activate an external service implementation, " "but another instance has already been dependency-injected." @@ -300,7 +300,7 @@ namespace lib { static void deactivateServiceAccess() { - ClassLock guard; + Lock guard; Depend::instance = nullptr; Depend::factory = Depend::disabledFactory; } diff --git a/src/lib/depend2.hpp b/src/lib/depend2.hpp index d6703fc64..c6a7d222c 100644 --- a/src/lib/depend2.hpp +++ b/src/lib/depend2.hpp @@ -170,6 +170,7 @@ namespace lib { class Depend { using Factory = std::function; + using Lock = ClassLock; static SRV* instance; static Factory factory; @@ -188,6 +189,7 @@ namespace lib { SRV& operator() () { + Lock guard; if (!instance) retrieveInstance(); // ENSURE (instance); @@ -198,7 +200,7 @@ namespace lib { void retrieveInstance() { -// ClassLock guard; +// Lock guard; // if (!instance) // { diff --git a/wiki/renderengine.html b/wiki/renderengine.html index fc95ceff3..e14c6c645 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -1984,6 +1984,7 @@ The following table lists averaged results in relative numbers, in relation to a |direct invoke shared local object | 15.13| 16.30| ''1.00''| 1.59| |invoke existing object through unique_ptr | 60.76| 63.20| 1.20| 1.64| |lazy init unprotected (not threadsafe) | 27.29| 26.57| 2.37| 3.58| +|lazy init always mutex protected | 179,62| 10917.18| 86.40| 6661.23| These benchmarks used a dummy service class holding a volatile int, initialised to a random value. The complete code was visible to the compiler and thus eligible for inlining. After accessing this dummy object through the means listed in the table, the benchmarked code retrieved this value repeatedly and compared it to zero. The concurrent measurement used 8 threads (number of cores); as expected, the unprotected lazy init crashed several times randomly during those tests.