1 //=============================================================================
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
29 * -t: Measure the performance of native thread creation
31 * On NT, this is CreateThread (). Currently, only
32 * these two platforms are implemented.
34 * -m: Measure the performance of Thread_Manager::spawn_n
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
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")
66 #define SUBPROGRAM ACE_TEXT ("date")
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
)
80 extern "C" void *ace_empty (void*)
87 prof_ace_process (size_t iteration
)
91 ACE_Process_Options popt
;
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
;
106 for (size_t c
= 0; c
< iteration
; c
++)
110 result
= aProcess
.spawn (popt
);
114 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "process.spawn"), -1);
115 else if (!do_exec_after_fork
&& result
== 0)
119 ptimer
.elapsed_time (et
);
120 time
+= et
.real_time
;
124 return time
/ iteration
;
131 prof_fork (size_t iteration
)
133 #if !defined (ACE_LACKS_EXEC)
136 ACE_Profile_Timer ptimer
;
137 ACE_Profile_Timer::ACE_Elapsed_Time et
;
140 iteration
*= MULTIPLY_FACTOR
;
142 for (size_t i
= 0; i
< iteration
; i
++)
146 switch (ACE_OS::fork ())
149 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "process.spawn"), -1);
157 ptimer
.elapsed_time (et
);
158 time
+= et
.real_time
;
161 return time
/ iteration
;
166 ACE_UNUSED_ARG (iteration
);
167 ACE_ERROR_RETURN ((LM_ERROR
, "fork () is not supported on this platform."), -1);
172 prof_native_thread (size_t iteration
)
174 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
177 ACE_Profile_Timer ptimer
;
178 ACE_Profile_Timer::ACE_Elapsed_Time et
;
181 for (size_t i
= 0; i
< iteration
; i
++)
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
),
195 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "CreateThread"), -1);
196 //FUZZ: enable check_for_lack_ACE_OS
199 ptimer
.elapsed_time (et
);
200 time
+= et
.real_time
;
202 iteration
*= MULTIPLY_FACTOR
;
203 return time
/ iteration
;
208 ACE_UNUSED_ARG (iteration
);
209 ACE_ERROR_RETURN ((LM_ERROR
, "Testing of native threads is not supported on this platform.\n"), -1);
214 prof_ace_os_thread (size_t iteration
)
216 #if defined (ACE_HAS_THREADS)
219 ACE_Profile_Timer ptimer
;
220 ACE_Profile_Timer::ACE_Elapsed_Time et
;
223 for (size_t i
= 0; i
< iteration
; i
++)
228 for (size_t j
= 0; j
< MULTIPLY_FACTOR
; j
++)
229 if (ACE_OS::thr_create ((ACE_THR_FUNC
) ace_empty
,
233 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "CreateThread"), -1);
236 ptimer
.elapsed_time (et
);
237 time
+= et
.real_time
;
239 iteration
*= MULTIPLY_FACTOR
;
240 return time
/ iteration
;
245 ACE_UNUSED_ARG (iteration
);
246 ACE_ERROR_RETURN ((LM_ERROR
, "Threads are not supported on this platform.\n"), -1);
251 prof_tm_thread (size_t iteration
)
253 #if defined (ACE_HAS_THREADS)
256 ACE_Profile_Timer ptimer
;
257 ACE_Profile_Timer::ACE_Elapsed_Time et
;
260 for (size_t i
= 0; i
< iteration
; i
++)
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);
272 ptimer
.elapsed_time (et
);
273 time
+= et
.real_time
;
275 iteration
*= MULTIPLY_FACTOR
;
276 return time
/ iteration
;
281 ACE_UNUSED_ARG (iteration
);
282 ACE_ERROR_RETURN ((LM_ERROR
, "Threads are not supported on this platform."), -1);
287 prof_mutex_base (size_t iteration
)
289 #if defined (ACE_HAS_THREADS)
290 ACE_Thread_Mutex plain
;
293 ACE_Profile_Timer ptimer
;
294 ACE_Profile_Timer::ACE_Elapsed_Time et
;
297 for (size_t i
= 0; i
< iteration
; i
++)
302 for (size_t j
=0; j
< MULTIPLY_FACTOR
; j
++)
309 ptimer
.elapsed_time (et
);
310 time
+= et
.real_time
;
312 iteration
*= MULTIPLY_FACTOR
;
313 return time
/ iteration
;
318 ACE_UNUSED_ARG (iteration
);
319 ACE_ERROR_RETURN ((LM_ERROR
, "Threads are not supported on this platform."), -1);
324 ACE_TMAIN (int argc
, ACE_TCHAR
* argv
[])
326 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT("n:l:pftahmxe"));
328 size_t iteration
= 10;
329 Profiler profiler
= 0;
330 const char *profile_name
= 0;
332 while ((c
=get_opt ()) != -1)
337 iteration
= ACE_OS::atoi (get_opt
.opt_arg ());
340 MULTIPLY_FACTOR
= static_cast<size_t> (ACE_OS::atoi (get_opt
.opt_arg ()));
342 case 'p': // test ACE_Process.spawn ()
343 profiler
= prof_ace_process
;
344 profile_name
= "ACE_Process.spawn ()";
346 case 'f': // test fork ()
347 profiler
= prof_fork
;
348 profile_name
= "fork ()";
350 case 't': // test native thread creation
351 profiler
= prof_native_thread
;
352 profile_name
= "native threads";
354 case 'a': // test ACE_OS::thr_create
355 profiler
= prof_ace_os_thread
;
356 profile_name
= "ACE_OS::thr_create ()";
359 profiler
= prof_tm_thread
;
360 profile_name
= "ACE_Thread_Manager::spawn_n ()";
363 profiler
= prof_mutex_base
;
364 profile_name
= "ACE_Thread_Mutex Baseline";
366 case 'h': // use high resolution timer
367 ACE_High_Res_Timer::get_env_global_scale_factor ();
370 do_exec_after_fork
= true;
378 ACE_ERROR_RETURN ((LM_ERROR
, "Usage: childbirth_time {-p|-f|-t|-a|-m|-x} [-n ###] [-L ###] [-h] [-e]\n"), 1);
381 double time
= profiler (iteration
);
383 ACE_DEBUG ((LM_DEBUG
,
384 "Average performance of %d iterations of %C: %.0f usec\n",
385 iteration
* MULTIPLY_FACTOR
, profile_name
, time
* 1e6
));