Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / performance-tests / Misc / childbirth_time.cpp
blob2cefc86ec35fca6825960a55b2e979763f6f7b64
1 //=============================================================================
2 /**
3 * @file childbirth_time.cpp
5 * This program is used to measure various child-creation mechanisms
6 * on various platforms. By default, the program measure the time
7 * to 'fork' a new process using ACE_Process.spawn (). Other tests
8 * are possible as described below. James Hu provides the idea to
9 * batch measuring threads creation.
11 * Usage: childbirth_time [-n ###] [-l ###] [-p|-f|-t|-a|-m|-x] [-h] [-e]
13 * -n ###: Specify number of iteration in tens. If this
14 * option is not specified, the default is
15 * MULTIPLY_FACTOR * (100 iterations,) which is
16 * equivalent to -n 10.
18 * -l ###: Specify MULTIPLY_FACTOR. Default is 10.
20 * *-p: Measure the performance of forking a child process
21 * and exec an "empty" program. This test uses
22 * ACE_Process.spawn (). (Default)
24 * -f: Measure the performance of native "fork" function
25 * call. Notice that there is no equivalent NT
26 * function calls and this option is only available
27 * on UN*X platform.
29 * -t: Measure the performance of native thread creation
30 * mechanisms.
31 * On NT, this is CreateThread (). Currently, only
32 * these two platforms are implemented.
34 * -m: Measure the performance of Thread_Manager::spawn_n
35 * method.
37 * -x: Test the baseline performance of ACE_Thread_Mutex.
38 * This really doesn't belong here
40 * -a: Measure the performance of thread creation using
41 * ACE_OS::thr_create ().
43 * -h: Use High Resolution Timer if supported by platform.
45 * -e: Exec a program after fork (). This option has no
46 * effect on NT.
48 * @author Nanbor Wang
50 //=============================================================================
52 // Process Creation profiling
53 #include "ace/OS_NS_unistd.h"
54 #include "ace/OS_main.h"
55 #include "ace/Get_Opt.h"
56 #include "ace/Process.h"
57 #include "ace/Profile_Timer.h"
58 #include "ace/Thread_Manager.h"
60 #define ACE_STOP_SIGN ACE_OS::sleep (0)
62 #define MAX_NO_ITERATION 10000
63 #if defined (ACE_WIN32)
64 #define SUBPROGRAM ACE_TEXT ("date.exe")
65 #else
66 #define SUBPROGRAM ACE_TEXT ("date")
67 #endif
69 size_t MULTIPLY_FACTOR = 10;
70 typedef double (*Profiler)(size_t);
71 static bool do_exec_after_fork = false;
73 /// do nothing thread function
74 #if defined (ACE_HAS_WTHREADS)
75 DWORD WINAPI ace_empty (LPVOID)
77 return 0;
79 #else
80 extern "C" void *ace_empty (void*)
82 return 0;
84 #endif
86 static double
87 prof_ace_process (size_t iteration)
89 if (iteration != 0)
91 ACE_Process_Options popt;
92 ACE_Process aProcess;
94 popt.command_line (SUBPROGRAM);
96 iteration *= MULTIPLY_FACTOR;
98 if (!do_exec_after_fork)
99 popt.creation_flags (ACE_Process_Options::NO_EXEC);
101 ACE_Profile_Timer ptimer;
102 ACE_Profile_Timer::ACE_Elapsed_Time et;
103 double time = 0;
104 pid_t result;
106 for (size_t c = 0; c < iteration; c++)
108 ACE_STOP_SIGN;
109 ptimer.start ();
110 result = aProcess.spawn (popt);
111 ptimer.stop ();
113 if (result == -1)
114 ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "process.spawn"), -1);
115 else if (!do_exec_after_fork && result == 0)
116 ACE_OS::exit (0) ;
117 else
119 ptimer.elapsed_time (et);
120 time += et.real_time;
124 return time / iteration;
126 else
127 return -1.0;
130 static double
131 prof_fork (size_t iteration)
133 #if !defined (ACE_LACKS_EXEC)
134 if (iteration != 0)
136 ACE_Profile_Timer ptimer;
137 ACE_Profile_Timer::ACE_Elapsed_Time et;
138 double time = 0;
140 iteration *= MULTIPLY_FACTOR;
142 for (size_t i = 0; i < iteration; i++)
144 ACE_STOP_SIGN;
145 ptimer.start ();
146 switch (ACE_OS::fork ())
148 case -1:
149 ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "process.spawn"), -1);
150 /* NOTREACHED */
151 case 0:
152 ACE_OS::exit (0);
153 /* NOTREACHED */
154 break;
155 default:
156 ptimer.stop ();
157 ptimer.elapsed_time (et);
158 time += et.real_time;
161 return time / iteration;
163 else
164 return -1.0;
165 #else
166 ACE_UNUSED_ARG (iteration);
167 ACE_ERROR_RETURN ((LM_ERROR, "fork () is not supported on this platform."), -1);
168 #endif
171 static double
172 prof_native_thread (size_t iteration)
174 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
175 if (iteration != 0)
177 ACE_Profile_Timer ptimer;
178 ACE_Profile_Timer::ACE_Elapsed_Time et;
179 double time = 0;
181 for (size_t i = 0; i < iteration; i++)
183 ACE_STOP_SIGN;
184 ptimer.start ();
185 for (size_t j = 0; j < MULTIPLY_FACTOR; j++)
187 #if defined (ACE_HAS_WTHREADS)
188 if (::CreateThread (0,
190 LPTHREAD_START_ROUTINE (ace_empty),
192 CREATE_SUSPENDED,
193 0) == 0)
194 #endif
195 ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "CreateThread"), -1);
196 //FUZZ: enable check_for_lack_ACE_OS
198 ptimer.stop ();
199 ptimer.elapsed_time (et);
200 time += et.real_time;
202 iteration *= MULTIPLY_FACTOR;
203 return time / iteration;
205 else
206 return -1.0;
207 #else
208 ACE_UNUSED_ARG (iteration);
209 ACE_ERROR_RETURN ((LM_ERROR, "Testing of native threads is not supported on this platform.\n"), -1);
210 #endif
213 static double
214 prof_ace_os_thread (size_t iteration)
216 #if defined (ACE_HAS_THREADS)
217 if (iteration != 0)
219 ACE_Profile_Timer ptimer;
220 ACE_Profile_Timer::ACE_Elapsed_Time et;
221 double time = 0;
223 for (size_t i = 0; i < iteration; i++)
225 ACE_STOP_SIGN;
226 ptimer.start ();
228 for (size_t j = 0; j < MULTIPLY_FACTOR; j++)
229 if (ACE_OS::thr_create ((ACE_THR_FUNC) ace_empty,
231 THR_SUSPENDED,
232 0) == -1)
233 ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "CreateThread"), -1);
235 ptimer.stop ();
236 ptimer.elapsed_time (et);
237 time += et.real_time;
239 iteration *= MULTIPLY_FACTOR;
240 return time / iteration;
242 else
243 return -1.0;
244 #else
245 ACE_UNUSED_ARG (iteration);
246 ACE_ERROR_RETURN ((LM_ERROR, "Threads are not supported on this platform.\n"), -1);
247 #endif
250 static double
251 prof_tm_thread (size_t iteration)
253 #if defined (ACE_HAS_THREADS)
254 if (iteration != 0)
256 ACE_Profile_Timer ptimer;
257 ACE_Profile_Timer::ACE_Elapsed_Time et;
258 double time = 0;
260 for (size_t i = 0; i < iteration; i++)
262 ACE_STOP_SIGN;
263 ptimer.start ();
265 if (ACE_Thread_Manager::instance ()->spawn_n (MULTIPLY_FACTOR,
266 (ACE_THR_FUNC) ace_empty,
268 THR_SUSPENDED) == -1)
269 ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "CreateThread"), -1);
271 ptimer.stop ();
272 ptimer.elapsed_time (et);
273 time += et.real_time;
275 iteration *= MULTIPLY_FACTOR;
276 return time / iteration;
278 else
279 return -1.0;
280 #else
281 ACE_UNUSED_ARG (iteration);
282 ACE_ERROR_RETURN ((LM_ERROR, "Threads are not supported on this platform."), -1);
283 #endif
286 static double
287 prof_mutex_base (size_t iteration)
289 #if defined (ACE_HAS_THREADS)
290 ACE_Thread_Mutex plain;
291 if (iteration != 0)
293 ACE_Profile_Timer ptimer;
294 ACE_Profile_Timer::ACE_Elapsed_Time et;
295 double time = 0;
297 for (size_t i = 0; i < iteration; i++)
299 ACE_STOP_SIGN;
300 ptimer.start ();
302 for (size_t j=0; j < MULTIPLY_FACTOR; j++)
304 plain.acquire ();
305 plain.release ();
308 ptimer.stop ();
309 ptimer.elapsed_time (et);
310 time += et.real_time;
312 iteration *= MULTIPLY_FACTOR;
313 return time / iteration;
315 else
316 return -1.0;
317 #else
318 ACE_UNUSED_ARG (iteration);
319 ACE_ERROR_RETURN ((LM_ERROR, "Threads are not supported on this platform."), -1);
320 #endif
324 ACE_TMAIN (int argc, ACE_TCHAR* argv[])
326 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("n:l:pftahmxe"));
327 int c;
328 size_t iteration = 10;
329 Profiler profiler = 0;
330 const char *profile_name = 0;
332 while ((c=get_opt ()) != -1)
334 switch (c)
336 case 'n':
337 iteration = ACE_OS::atoi (get_opt.opt_arg ());
338 break;
339 case 'l':
340 MULTIPLY_FACTOR = static_cast<size_t> (ACE_OS::atoi (get_opt.opt_arg ()));
341 break;
342 case 'p': // test ACE_Process.spawn ()
343 profiler = prof_ace_process;
344 profile_name = "ACE_Process.spawn ()";
345 break;
346 case 'f': // test fork ()
347 profiler = prof_fork;
348 profile_name = "fork ()";
349 break;
350 case 't': // test native thread creation
351 profiler = prof_native_thread;
352 profile_name = "native threads";
353 break;
354 case 'a': // test ACE_OS::thr_create
355 profiler = prof_ace_os_thread;
356 profile_name = "ACE_OS::thr_create ()";
357 break;
358 case 'm':
359 profiler = prof_tm_thread;
360 profile_name = "ACE_Thread_Manager::spawn_n ()";
361 break;
362 case 'x':
363 profiler = prof_mutex_base;
364 profile_name = "ACE_Thread_Mutex Baseline";
365 break;
366 case 'h': // use high resolution timer
367 ACE_High_Res_Timer::get_env_global_scale_factor ();
368 break;
369 case 'e':
370 do_exec_after_fork = true;
371 break;
372 default:
373 break;
377 if (profiler == 0)
378 ACE_ERROR_RETURN ((LM_ERROR, "Usage: childbirth_time {-p|-f|-t|-a|-m|-x} [-n ###] [-L ###] [-h] [-e]\n"), 1);
379 else
381 double time = profiler (iteration);
382 if (time > 0)
383 ACE_DEBUG ((LM_DEBUG,
384 "Average performance of %d iterations of %C: %.0f usec\n",
385 iteration * MULTIPLY_FACTOR, profile_name, time * 1e6));
387 return 0;