summaryrefslogtreecommitdiff
path: root/tests/Notify_Performance_Test.cpp
blob: a88d9fa7da3fe72531c74b25199b6c3d6d58c8c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
// $Id$

// ============================================================================
//
// = LIBRARY
//    tests
//
// = FILENAME
//    Notify_Performance_Test.cpp
//
// = DESCRIPTION
//    This test is used to time the notification mechanisms of the
//    ACE_Reactors. Both the WFMO_Reactor and Select_Reactor can be
//    tested. The notify() mechanism can also be tested with or
//    without data.
//
// = AUTHOR
//    Irfan Pyarali <irfan@cs.wustl.edu>
//
// ============================================================================

#include "test_config.h"
#include "ace/Profile_Timer.h"
#include "ace/Get_Opt.h"
#include "ace/Thread_Manager.h"
#include "ace/Reactor.h"
#include "ace/WFMO_Reactor.h"
#include "ace/Select_Reactor.h"
#include "ace/Auto_Ptr.h"
#include "ace/Synch.h"
#include "ace/Atomic_Op.h"

ACE_RCSID(tests, Notify_Performance_Test, "$Id$")

#if defined (ACE_HAS_THREADS)

// Number of client (user) threads
static long opt_nthreads = 1;

// Number of notify calls
static int opt_nloops = 20000;

// Use the WFMO_Reactor
static int opt_wfmo_reactor = 0;

// Use the Select_Reactor
static int opt_select_reactor = 0;

// Pass data through the notify call
static int opt_pass_notify_data = 0;

// Simple no-op handler
class Handler : public ACE_Event_Handler
{
public:
  virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE);
  // The Handler callbacks.
};

int
Handler::handle_exception (ACE_HANDLE handle)
{
  ACE_UNUSED_ARG (handle);

  return 0;
}

// Execute the client tests.

static void *
client (void *arg)
{
  // Number of client (user) threads
  static ACE_Atomic_Op<ACE_Thread_Mutex, long> thread_counter;
  thread_counter = opt_nthreads;

  // To pass or not to pass is the question
  Handler *handler = 0;
  if (!opt_pass_notify_data)
    handler = 0;
  else
    handler = (Handler *) arg;

  for (int i = 0; i < opt_nloops; i++)
    ACE_Reactor::instance ()->notify (handler);

  if (--thread_counter == 0)
    ACE_Reactor::end_event_loop ();

  return 0;
}

// Sets up the correct reactor (based on platform and options)

static void
create_reactor (void)
{
  ACE_Reactor_Impl *impl = 0;

  if (opt_wfmo_reactor)
    {
#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
      ACE_NEW (impl, ACE_WFMO_Reactor);
#endif /* ACE_WIN32 */
    }
  else if (opt_select_reactor)
    {
      ACE_NEW (impl, ACE_Select_Reactor);
    }
  ACE_Reactor *reactor = 0;
  ACE_NEW (reactor, ACE_Reactor (impl));
  ACE_Reactor::instance (reactor);
}

static void
print_results (ACE_Profile_Timer::ACE_Elapsed_Time &et)
{
  const ACE_TCHAR *reactor_type = 0;
  if (opt_wfmo_reactor)
    reactor_type = ACE_TEXT ("WFMO_Reactor");
  else if (opt_select_reactor)
    reactor_type = ACE_TEXT ("Select_Reactor");
  else
    reactor_type = ACE_TEXT ("Platform's default Reactor");

  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("\nNotify_Performance Test statistics:\n\n")));
  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("\tReactor Type: %s\n"),
              reactor_type));
  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("\tWorker threads (calling notify()): %d\n"),
              opt_nthreads));
  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("\tIteration per thread: %d\n"),
              opt_nloops));
  if (opt_pass_notify_data)
    ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("\tData was passed in the notify() call\n")));
  else
    ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("\tNo data was passed in the notify() call\n")));

  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("\n\tTiming results notify() call:\n")));
  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n\n"),
              et.real_time,
              et.user_time,
              et.system_time));
}

int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
  ACE_START_TEST (ACE_TEXT ("Notify_Performance_Test"));

  ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("swdc:l:"));

  for (int c; (c = getopt ()) != -1; )
    switch (c)
      {
      case 's':
        opt_select_reactor = 1;
        break;
      case 'w':
        opt_wfmo_reactor = 1;
        break;
      case 'c':
        opt_nthreads = ACE_OS::atoi (getopt.opt_arg ());
        break;
      case 'l':
        opt_nloops = ACE_OS::atoi (getopt.opt_arg ());
        break;
      case 'd':
        opt_pass_notify_data = 1;
        break;
      }

  // Sets up the correct reactor (based on platform and options)
  create_reactor ();

  // Manage memory automagically.
  auto_ptr<ACE_Reactor> reactor (ACE_Reactor::instance ());
  auto_ptr<ACE_Reactor_Impl> impl;

  // If we are using other that the default implementation, we must
  // clean up.
  if (opt_select_reactor || opt_wfmo_reactor)
    {
      auto_ptr<ACE_Reactor_Impl> auto_impl (ACE_Reactor::instance ()->implementation ());
      impl = auto_impl;
    }

  // Callback object
  Handler handler;

  // Spawn worker threads
  if (ACE_Thread_Manager::instance ()->spawn_n
      (opt_nthreads,
       ACE_THR_FUNC (client),
       (void *) &handler,
       THR_NEW_LWP | THR_DETACHED) == -1)
    ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P|%t) %p\n%a"), ACE_TEXT ("thread create failed")));

  // Timer business
  ACE_Profile_Timer timer;
  timer.start ();

  // Run event loop
  ACE_Reactor::instance()->run_reactor_event_loop ();

  timer.stop ();

  ACE_Profile_Timer::ACE_Elapsed_Time et;
  timer.elapsed_time (et);

  // Print results
  print_results (et);

  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("(%P|%t) waiting for the worker threads...\n")));

  // Wait for all worker to get done.
  ACE_Thread_Manager::instance ()->wait ();

  ACE_END_TEST;
  return 0;
}

#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class auto_ptr<ACE_Reactor>;
template class ACE_Auto_Basic_Ptr<ACE_Reactor>;
template class auto_ptr<ACE_Reactor_Impl>;
template class ACE_Auto_Basic_Ptr<ACE_Reactor_Impl>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate auto_ptr<ACE_Reactor>
#pragma instantiate ACE_Auto_Basic_Ptr<ACE_Reactor>
#pragma instantiate auto_ptr<ACE_Reactor_Impl>
#pragma instantiate ACE_Auto_Basic_Ptr<ACE_Reactor_Impl>
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */

#else
int
ACE_TMAIN (int, ACE_TCHAR *[])
{
  ACE_START_TEST (ACE_TEXT ("Notify_Performance_Test"));

  ACE_ERROR ((LM_INFO,
              ACE_TEXT ("threads not supported on this platform\n")));

  ACE_END_TEST;
  return 0;
}
#endif /* ACE_HAS_THREADS */