2 //=============================================================================
4 * @file Reactor_Performance_Test.cpp
6 * This test is used to time the dispatching mechanisms of the
7 * <ACE_Reactor>s. Both the <ACE_WFMO_Reactor> and
8 * <ACE_Select_Reactor> can be tested.
10 * @author Irfan Pyarali <irfan@cs.wustl.edu>
12 //=============================================================================
14 #include "test_config.h"
15 #include "Reactor_Performance_Test.h"
16 #include "ace/Profile_Timer.h"
17 #include "ace/Get_Opt.h"
18 #include "ace/SOCK_Connector.h"
19 #include "ace/SOCK_Acceptor.h"
20 #include "ace/Acceptor.h"
21 #include "ace/Connector.h"
22 #include "ace/Reactor.h"
23 #include "ace/WFMO_Reactor.h"
24 #include "ace/Select_Reactor.h"
25 #include "ace/Auto_Ptr.h"
27 #if defined (ACE_HAS_THREADS) && !defined ACE_LACKS_ACCEPT
29 static const char ACE_ALPHABET
[] = "abcdefghijklmnopqrstuvwxyz";
31 // Number of client (user) threads
32 static int opt_nconnections
= 5;
34 // Number of data exchanges
35 static int opt_nloops
= 200;
37 // Use the WFMO_Reactor
38 static int opt_wfmo_reactor
= 0;
40 // Use the Select_Reactor
41 static int opt_select_reactor
= 0;
43 // Extra debug messages
44 static int opt_debug
= 0;
46 int Read_Handler::waiting_
= 0;
49 Read_Handler::set_countdown (int nconnections
)
51 Read_Handler::waiting_
= nconnections
;
54 // Initialize the Svc_Handler
56 Read_Handler::open (void *)
58 if (this->peer ().enable (ACE_NONBLOCK
) == -1)
59 ACE_ERROR_RETURN ((LM_ERROR
,
60 ACE_TEXT ("(%t) Read_Handler::open, cannot set non blocking mode\n")),
63 if (reactor ()->register_handler (this, READ_MASK
) == -1)
64 ACE_ERROR_RETURN ((LM_ERROR
,
65 ACE_TEXT ("(%t) Read_Handler::open, cannot register handler\n")),
69 ACE_TEXT ("(%t) created svc_handler for handle %d\n"),
74 // Handle incoming data
76 Read_Handler::handle_input (ACE_HANDLE handle
)
78 ACE_UNUSED_ARG (handle
);
83 ssize_t result
= this->peer ().recv (buf
, sizeof (buf
) - 1);
91 ACE_TEXT ("(%t) Read_Handler::handle_input: %s\n"),
97 if (errno
== EWOULDBLOCK
)
101 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("handle_input: %p (errno: %d)\n"),
102 ACE_TEXT ("recv"), ACE_ERRNO_GET
));
104 // This will cause handle_close to get called.
110 // This will cause handle_close to get called.
115 ACE_NOTREACHED (return 0);
118 // Handle connection shutdown.
121 Read_Handler::handle_close (ACE_HANDLE handle
,
122 ACE_Reactor_Mask close_mask
)
124 ACE_UNUSED_ARG (handle
);
125 ACE_UNUSED_ARG (close_mask
);
130 // If no connections are open.
132 ACE_Reactor::instance ()->end_reactor_event_loop ();
134 ACE_DEBUG ((LM_DEBUG
,
135 ACE_TEXT ("(%t) Read_Handler::handle_close closing down\n")));
143 Write_Handler::open (void *)
149 Write_Handler::send_data (void)
151 int send_size
= sizeof (ACE_ALPHABET
) - 1;
153 if (this->peer ().send_n (ACE_ALPHABET
,
154 send_size
) != send_size
)
155 ACE_ERROR_RETURN ((LM_ERROR
,
156 ACE_TEXT ("(%t) %p\n"),
157 ACE_TEXT ("send_n")),
162 // Connection factories
163 typedef ACE_Connector
<Write_Handler
, ACE_SOCK_CONNECTOR
> CONNECTOR
;
164 typedef ACE_Acceptor
<Read_Handler
, ACE_SOCK_ACCEPTOR
> ACCEPTOR
;
166 // Execute the client tests.
170 ACE_DEBUG ((LM_DEBUG
,
171 ACE_TEXT ("(%t) running client\n")));
173 ACE_INET_Addr
*connection_addr
=
174 reinterpret_cast<ACE_INET_Addr
*> (arg
);
179 // Automagic memory cleanup.
180 Write_Handler
**temp_writers
= 0;
181 ACE_NEW_RETURN (temp_writers
,
182 Write_Handler
*[opt_nconnections
],
184 ACE_Auto_Basic_Array_Ptr
<Write_Handler
*> writers (temp_writers
);
186 ACE_TCHAR
*temp_failed
= 0;
187 ACE_NEW_RETURN (temp_failed
,
188 ACE_TCHAR
[opt_nconnections
],
190 ACE_Auto_Basic_Array_Ptr
<ACE_TCHAR
> failed_svc_handlers (temp_failed
);
192 // Automagic memory cleanup.
193 ACE_INET_Addr
*temp_addresses
;
194 ACE_NEW_RETURN (temp_addresses
,
195 ACE_INET_Addr
[opt_nconnections
],
197 ACE_Auto_Array_Ptr
<ACE_INET_Addr
> addresses (temp_addresses
);
200 for (i
= 0; i
< opt_nconnections
; i
++)
203 addresses
[i
] = *connection_addr
;
206 // Connection all <opt_nconnections> svc_handlers
207 int result
= connector
.connect_n (opt_nconnections
,
210 failed_svc_handlers
.get ());
213 // Print out the connections that failed...
214 for (i
= 0; i
< opt_nconnections
; i
++)
215 if (failed_svc_handlers
.get ()[i
])
217 ACE_INET_Addr failed_addr
= addresses
.get()[i
];
218 ACE_ERROR ((LM_ERROR
,
219 ACE_TEXT ("(%t) connection failed to %s, %d\n"),
220 failed_addr
.get_host_name (),
221 failed_addr
.get_port_number ()));
226 // If no connections failed (result == 0) then there should be valid
227 // ACE_Svc_handler pointers in each writers[] position. Iterate to
229 for (int j
= 0; j
< opt_nloops
; j
++)
230 for (i
= 0; i
< opt_nconnections
; i
++)
231 if (writers
[i
]->send_data () == -1)
232 ACE_ERROR_RETURN ((LM_ERROR
,
233 ACE_TEXT ("(%t) %p\n"),
234 ACE_TEXT ("writer::send_data")),
237 for (i
= 0; i
< opt_nconnections
; i
++)
238 writers
[i
]->destroy ();
240 ACE_DEBUG ((LM_DEBUG
,
241 ACE_TEXT ("(%t) finishing client\n")));
245 // Sets up the correct reactor (based on platform and options).
248 create_reactor (void)
250 ACE_Reactor_Impl
*impl
= 0;
252 if (opt_wfmo_reactor
)
254 #if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 == 1)
257 #endif /* ACE_HAS_WINSOCK2 == 1 */
259 else if (opt_select_reactor
)
263 ACE_Reactor
*reactor
= 0;
266 ACE_Reactor::instance (reactor
);
272 print_results (ACE_Profile_Timer::ACE_Elapsed_Time
&et
)
274 const ACE_TCHAR
*reactor_type
= 0;
276 if (opt_wfmo_reactor
)
277 reactor_type
= ACE_TEXT ("WFMO_Reactor");
278 else if (opt_select_reactor
)
279 reactor_type
= ACE_TEXT ("Select_Reactor");
281 reactor_type
= ACE_TEXT ("Platform's default Reactor");
283 ACE_DEBUG ((LM_DEBUG
,
284 ACE_TEXT ("\n\tReactor_Performance Test statistics:\n\n")));
285 ACE_DEBUG ((LM_DEBUG
,
286 ACE_TEXT ("\tReactor Type: %s\n"),
288 ACE_DEBUG ((LM_DEBUG
,
289 ACE_TEXT ("\tConnections: %d\n"),
291 ACE_DEBUG ((LM_DEBUG
,
292 ACE_TEXT ("\tIteration per connection: %d\n"),
295 ACE_DEBUG ((LM_DEBUG
,
296 ACE_TEXT ("\n\tTiming results:\n")));
297 ACE_DEBUG ((LM_DEBUG
,
298 ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n\n"),
305 run_main (int argc
, ACE_TCHAR
*argv
[])
307 ACE_START_TEST (ACE_TEXT ("Reactor_Performance_Test"));
309 //FUZZ: disable check_for_lack_ACE_OS
310 ACE_Get_Opt
getopt (argc
, argv
, ACE_TEXT ("dswc:l:"), 1);
311 for (int c
; (c
= getopt ()) != -1; )
312 //FUZZ: enble check_for_lack_ACE_OS
316 opt_select_reactor
= 1;
319 opt_wfmo_reactor
= 1;
322 opt_nconnections
= ACE_OS::atoi (getopt
.opt_arg ());
325 opt_nloops
= ACE_OS::atoi (getopt
.opt_arg ());
332 // Sets up the correct reactor (based on platform and options).
335 // Manage memory automagically.
336 auto_ptr
<ACE_Reactor
> reactor (ACE_Reactor::instance ());
337 auto_ptr
<ACE_Reactor_Impl
> impl
;
339 // If we are using other that the default implementation, we must
341 if (opt_select_reactor
|| opt_wfmo_reactor
)
343 auto_ptr
<ACE_Reactor_Impl
> auto_impl (ACE_Reactor::instance ()->implementation ());
347 Read_Handler::set_countdown (opt_nconnections
);
351 ACE_INET_Addr server_addr
;
353 // Bind acceptor to any port and then find out what the port was.
354 ACE_INET_Addr
local_addr (ACE_sap_any_cast (const ACE_INET_Addr
&));
355 if (acceptor
.open (local_addr
) == -1
356 || acceptor
.acceptor ().get_local_addr (server_addr
) == -1)
357 ACE_ERROR_RETURN ((LM_ERROR
,
358 ACE_TEXT ("(%t) %p\n"),
362 ACE_DEBUG ((LM_DEBUG
,
363 ACE_TEXT ("(%t) starting server at port %d\n"),
364 server_addr
.get_port_number ()));
366 ACE_INET_Addr
connection_addr (server_addr
.get_port_number (),
367 ACE_DEFAULT_SERVER_HOST
);
369 if (ACE_Thread_Manager::instance ()->spawn
370 (ACE_THR_FUNC (client
),
371 (void *) &connection_addr
,
372 THR_NEW_LWP
| THR_DETACHED
) == -1)
373 ACE_ERROR ((LM_ERROR
,
374 ACE_TEXT ("(%t) %p\n"),
375 ACE_TEXT ("thread create failed")));
377 ACE_Time_Value
run_limit (opt_nloops
/ 10);
379 ACE_Profile_Timer timer
;
382 ACE_Reactor::instance ()->run_reactor_event_loop (run_limit
);
385 ACE_Profile_Timer::ACE_Elapsed_Time et
;
386 timer
.elapsed_time (et
);
391 ACE_DEBUG ((LM_DEBUG
,
392 ACE_TEXT ("(%t) waiting for the client thread...\n")));
394 ACE_Thread_Manager::instance ()->wait ();
402 run_main (int, ACE_TCHAR
*[])
404 ACE_START_TEST (ACE_TEXT ("Reactor_Performance_Test"));
407 ACE_TEXT ("threads/accept not supported on this platform\n")));
412 #endif /* ACE_HAS_THREADS && ! ACE_LACKS_ACCEPT */