Cleanup Solaris support
[ACE_TAO.git] / ACE / performance-tests / Misc / test_mutex.cpp
blob74986ede573ed79a074b110314e9b79e44dc92ea
1 // This test program illustrates the performance difference between
2 // three versions of wrappers for thread mutexes. These three
3 // versions exercise various combinations of the following classes:
4 //
5 // Thread_Mutex --
6 // This version is just like ACE_Thread_Mutex, which doesn't use
7 // inheritance and dynamic binding.
8 //
9 // Mutex_Base --
10 // This is an abstract base class that defines the
11 // acquire()/release() interface.
13 // Thread_Mutex_Derived --
14 // This derived from Mutex_Base and uses inheritance and
15 // dynamic binding.
17 // The following are the results I got when running this on our
18 // SPARCstation 20 model 712:
20 // ./test_mutex 1000000
21 // iterations = 1000000
22 // Thread_Mutex
23 // real time = 1.727843 secs, user time = 1.729262 secs, system time = 0.000325 secs
24 // time per call = 1.747843 usecs
25 // Thread_Mutex_Derived
26 // real time = 1.730225 secs, user time = 1.724744 secs, system time = 0.000096 secs
27 // time per call = 1.730225 usecs
28 // Mutex_Base
29 // real time = 2.112831 secs, user time = 2.104245 secs, system time = 0.000095 secs
30 // time per call = 2.112831 usecs
32 // My conclusions are as follows:
34 // 1. If your C++ compiler optimizes calls to virtual functions that
35 // are made through instances of derived classes, then the
36 // performance of the Thread_Mutex and Thread_Mutex_Derived are
37 // essentially identical.
39 // 2. The overhead from using virtual functions is approximately
40 // 20%. Naturally, as the amount of contention goes up, the
41 // relative overhead of the virtual function calls will decrease.
43 // Keep in mind, however, that using virtual functions to implement
44 // the Thread_Mutex will make it infeasible to put instances of
45 // Thread_Mutex into shared memory since the vptrs won't point to the
46 // correct vtables...
48 #include "ace/Log_Msg.h"
49 #include "ace/Profile_Timer.h"
50 #include "ace/OS_main.h"
51 #include "ace/OS_NS_Thread.h"
53 #if defined (ACE_HAS_THREADS)
55 static const int DEFAULT_ITERATIONS = 100000000;
57 // A thread mutex that doesn't use virtual functions.
58 class Thread_Mutex
60 public:
61 Thread_Mutex ();
62 ~Thread_Mutex ();
63 int acquire ();
64 int release ();
66 private:
67 ACE_mutex_t mutex_;
70 Thread_Mutex::Thread_Mutex ()
72 ACE_OS::mutex_init (&this->mutex_);
75 Thread_Mutex::~Thread_Mutex ()
77 ACE_OS::mutex_destroy (&this->mutex_);
80 inline int
81 Thread_Mutex::acquire ()
83 return ACE_OS::mutex_lock (&this->mutex_);
86 inline int
87 Thread_Mutex::release ()
89 return ACE_OS::mutex_unlock (&this->mutex_);
92 // Base class for mutex, declares pure virtual functions.
93 class Mutex_Base
95 public:
96 virtual ~Mutex_Base ();
97 virtual int acquire () = 0;
98 virtual int release () = 0;
101 Mutex_Base::~Mutex_Base ()
105 // Subclass for threaded mutex, defines virtual functions.
106 class Thread_Mutex_Derived : public Mutex_Base
108 public:
109 Thread_Mutex_Derived ();
110 virtual ~Thread_Mutex_Derived ();
111 virtual int acquire ();
112 virtual int release ();
114 private:
115 ACE_mutex_t mutex_;
118 Thread_Mutex_Derived::Thread_Mutex_Derived ()
120 ACE_OS::mutex_init (&this->mutex_);
123 Thread_Mutex_Derived::~Thread_Mutex_Derived ()
125 ACE_OS::mutex_destroy (&this->mutex_);
128 inline int
129 Thread_Mutex_Derived::acquire ()
131 return ACE_OS::mutex_lock (&this->mutex_);
134 inline int
135 Thread_Mutex_Derived::release ()
137 return ACE_OS::mutex_unlock (&this->mutex_);
140 static Thread_Mutex thread_mutex;
141 static Thread_Mutex_Derived thread_mutex_derived;
142 static Mutex_Base *mutex_base = &thread_mutex_derived;
145 ACE_TMAIN (int argc, ACE_TCHAR *argv[])
147 ACE_Profile_Timer timer;
148 int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_ITERATIONS;
149 int i;
151 ACE_DEBUG ((LM_DEBUG, "iterations = %d\n", iterations));
153 timer.start ();
155 // Test the thread mutex (which doesn't use inheritance or dynamic
156 // binding).
158 for (i = 0; i < iterations; i++)
160 thread_mutex.acquire ();
161 thread_mutex.release ();
164 timer.stop ();
166 ACE_Profile_Timer::ACE_Elapsed_Time et;
168 timer.elapsed_time (et);
170 ACE_DEBUG ((LM_DEBUG, "Thread_Mutex\n"));
171 ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
172 et.real_time, et.user_time, et.system_time));
174 ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
175 (et.real_time / double (iterations)) * 1000000));
177 // Test the thread mutex derived (which does use inheritance or
178 // dynamic binding). Note that we call this via an instance of the
179 // derived class, so good C++ compilers should optimize the virtual
180 // function calls in this case.
182 timer.start ();
184 for (i = 0; i < iterations; i++)
186 thread_mutex_derived.acquire ();
187 thread_mutex_derived.release ();
190 timer.stop ();
192 timer.elapsed_time (et);
194 ACE_DEBUG ((LM_DEBUG, "Thread_Mutex_Derived\n"));
195 ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
196 et.real_time, et.user_time, et.system_time));
198 ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
199 (et.real_time / double (iterations)) * 1000000));
201 // Test the thread mutex derived (which does use inheritance or
202 // dynamic binding). Note that we call this via a pointer to the
203 // base class, which points to an instance of the derived class.
204 // Thus, C++ compilers won't be able to optimize the virtual
205 // function calls in this case.
207 timer.start ();
209 for (i = 0; i < iterations; i++)
211 mutex_base->acquire ();
212 mutex_base->release ();
215 timer.stop ();
217 timer.elapsed_time (et);
219 ACE_DEBUG ((LM_DEBUG, "Mutex_Base\n"));
220 ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
221 et.real_time, et.user_time, et.system_time));
223 ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
224 (et.real_time / double (iterations)) * 1000000));
225 return 0;
227 #else
229 ACE_TMAIN (int, ACE_TCHAR *[])
231 ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
232 return 0;
234 #endif /* ACE_HAS_THREADS */