Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / performance-tests / Misc / test_singleton.cpp
bloba3723f165ee97107ac41fa5d0d6220bec54da635
1 // This example illustrates the performance impact of using the
2 // Double-Checked Locking pattern compared with using the "standard"
3 // practice of acquiring and releasing a lock on every instance()
4 // call. In addition, we compare the performance of using the
5 // ACE_Singleton (which encapsulates the Double-Check Locking pattern)
6 // vs. hand-coding the pattern.
7 //
8 // Here's the output from running this test on our SPARCstation 20, model 712s.
9 //
10 // ./test_singleton 1000000
11 // iterations = 1000000
12 // ACE_Singleton
13 // real time = 0.193731 secs, user time = 0.190416 secs, system time = 0.000549 secs
14 // time per call = 0.193731 usecs
15 // DC_Singleton
16 // real time = 0.176208 secs, user time = 0.176045 secs, system time = 0.000092 secs
17 // time per call = 0.176208 usecs
18 // Mutex_Singleton
19 // real time = 3.160998 secs, user time = 3.121434 secs, system time = 0.000109 secs
20 // time per call = 3.160998 usecs
22 // As you can see, both Double-Checked Locking implementations are about
23 // 15 times faster than the standard mutex version. Moreover,
24 // this test is run with only a single thread, so there's no contention
25 // for the lock. If there were multiple threads contending for the lock,
26 // the Mutex_Singleton performance would get increasing worse...
28 #include "ace/OS_main.h"
29 #include "ace/Guard_T.h"
30 #include "ace/Profile_Timer.h"
31 #include "ace/Singleton.h"
32 #include "ace/Synch_Traits.h"
33 #include "ace/Log_Msg.h"
35 #include "test_singleton.h"
37 #if defined (ACE_HAS_THREADS)
39 static const int DEFAULT_ITERATIONS = 100000000;
41 class Mutex_Singleton
43 public:
44 Mutex_Singleton () {}
45 void svc () {}
46 static Mutex_Singleton *instance ();
48 private:
49 static ACE_SYNCH_MUTEX lock_;
50 static Mutex_Singleton *instance_;
53 ACE_SYNCH_MUTEX Mutex_Singleton::lock_;
55 Mutex_Singleton *Mutex_Singleton::instance_;
57 Mutex_Singleton *
58 Mutex_Singleton::instance ()
60 // Acquire the lock every time in.
61 ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, Mutex_Singleton::lock_, 0);
63 if (Mutex_Singleton::instance_ == 0)
64 ACE_NEW_RETURN (Mutex_Singleton::instance_, Mutex_Singleton, 0);
66 return Mutex_Singleton::instance_;
69 ACE_SYNCH_MUTEX DC_Singleton::lock_;
71 DC_Singleton *DC_Singleton::instance_;
73 DC_Singleton *
74 DC_Singleton::instance ()
76 if (DC_Singleton::instance_ == 0)
78 // Only lock if instance_ isn't 0.
79 ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, DC_Singleton::lock_, 0);
81 // Perform the Double-Check.
82 if (DC_Singleton::instance_ == 0)
83 ACE_NEW_RETURN (DC_Singleton::instance_, DC_Singleton, 0);
86 return DC_Singleton::instance_;
89 typedef ACE_Singleton <DC_Singleton, ACE_SYNCH_MUTEX> My_Singleton;
91 int
92 ACE_TMAIN (int argc, ACE_TCHAR *argv[])
94 ACE_Profile_Timer timer;
95 int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_ITERATIONS;
96 int i;
98 ACE_DEBUG ((LM_DEBUG, "iterations = %d\n", iterations));
100 // Test the ACE_Singleton performance (which uses Double-Checked
101 // Locking).
103 timer.start ();
105 for (i = 0; i < iterations; i++)
106 My_Singleton::instance ()->svc ();
108 timer.stop ();
110 ACE_Profile_Timer::ACE_Elapsed_Time et;
112 timer.elapsed_time (et);
114 ACE_DEBUG ((LM_DEBUG, "ACE_Singleton\n"));
115 ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
116 et.real_time, et.user_time, et.system_time));
118 ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
119 (et.real_time / double (iterations)) * 1000000));
121 // Test the hand-coded Singleton performance (which uses
122 // Double-Checked Locking).
124 timer.start ();
126 for (i = 0; i < iterations; i++)
127 DC_Singleton::instance ()->svc ();
129 timer.stop ();
131 timer.elapsed_time (et);
133 ACE_DEBUG ((LM_DEBUG, "DC_Singleton\n"));
134 ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
135 et.real_time, et.user_time, et.system_time));
137 ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
138 (et.real_time / double (iterations)) * 1000000));
140 // Test the Mutex_Singleton implementation (which does not use
141 // Double-Checked Locking).
143 timer.start ();
145 for (i = 0; i < iterations; i++)
146 Mutex_Singleton::instance ()->svc ();
148 timer.stop ();
150 timer.elapsed_time (et);
152 ACE_DEBUG ((LM_DEBUG, "Mutex_Singleton\n"));
153 ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
154 et.real_time, et.user_time, et.system_time));
156 ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
157 (et.real_time / double (iterations)) * 1000000));
159 return 0;
162 ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_Singleton, DC_Singleton, ACE_SYNCH_MUTEX);
164 #else
166 ACE_TMAIN (int, ACE_TCHAR *[])
168 ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
169 return 0;
171 #endif /* ACE_HAS_THREADS */