summaryrefslogtreecommitdiff
path: root/TAO/performance-tests/Cubit/TAO/MT_Cubit
diff options
context:
space:
mode:
authorWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:21 +0000
committerWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:21 +0000
commit3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (patch)
tree197c810e5f5bce17b1233a7cb8d7b50c0bcd25e2 /TAO/performance-tests/Cubit/TAO/MT_Cubit
parent6b846cf03c0bcbd8c276cb0af61a181e5f98eaae (diff)
downloadATCD-3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c.tar.gz
Repo restructuring
Diffstat (limited to 'TAO/performance-tests/Cubit/TAO/MT_Cubit')
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Cubit_Task.cpp259
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Cubit_Task.h88
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Globals.cpp227
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Globals.h219
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/MT_Cubit.mpc49
-rwxr-xr-xTAO/performance-tests/Cubit/TAO/MT_Cubit/MT_Cubit_Test102
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile.am140
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/README215
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/README.tests44
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp1147
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h372
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Timer.cpp56
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Timer.h61
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Util_Thread.cpp99
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/Util_Thread.h57
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp865
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h183
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit.idl39
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit_i.cpp77
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit_i.h66
-rwxr-xr-xTAO/performance-tests/Cubit/TAO/MT_Cubit/plot50
-rwxr-xr-xTAO/performance-tests/Cubit/TAO/MT_Cubit/run_test.pl74
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp394
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/server.h141
-rwxr-xr-xTAO/performance-tests/Cubit/TAO/MT_Cubit/summarize63
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/svc.conf8
-rw-r--r--TAO/performance-tests/Cubit/TAO/MT_Cubit/svc.conf.xml11
27 files changed, 5106 insertions, 0 deletions
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Cubit_Task.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Cubit_Task.cpp
new file mode 100644
index 00000000000..2fb15abdc38
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Cubit_Task.cpp
@@ -0,0 +1,259 @@
+// $Id$
+
+#include "ace/Sched_Params.h"
+#include "Globals.h"
+#include "Cubit_Task.h"
+#include "tao/TAO_Internal.h"
+#include "ace/Barrier.h"
+
+Cubit_Task::Cubit_Task (void)
+{
+ // No-op.
+}
+
+Cubit_Task::Cubit_Task (const char *args,
+ const char *orbname,
+ u_int num_of_objs,
+ ACE_Thread_Manager *thr_mgr,
+ u_int task_id)
+ : ACE_Task<ACE_SYNCH> (thr_mgr),
+ key_ ("Cubit"),
+ orbname_ ((char *) orbname),
+ orbargs_ ((char *) args),
+ num_of_objs_ (num_of_objs),
+ servants_ (0),
+ servants_iors_ (0),
+ task_id_ (task_id)
+{
+}
+
+int
+Cubit_Task::svc (void)
+{
+ ACE_hthread_t thr_handle;
+ ACE_Thread::self (thr_handle);
+ int prio;
+
+ // thr_getprio () on the current thread should never fail.
+
+ if (ACE_OS::thr_getprio (thr_handle, prio) == -1)
+ return -1;
+
+ // char buffer[BUFSIZ];
+ // sprintf (buffer, "server%d.log", this->task_id_);
+ // ACE_Log_Msg::instance()->clr_flags (ACE_Log_Msg::OSTREAM);
+ // ACE_Log_Msg::instance()->clr_flags (ACE_Log_Msg::STDERR);
+ // ACE_Log_Msg::instance()->clr_flags (ACE_Log_Msg::LOGGER);
+ // ofstream log (buffer);
+ // log.setf (ios::unitbuf);
+ // log.rdbuf()->unbuffered (1);
+ //ACE_Log_Msg::instance()->msg_ostream (&log);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Beginning Cubit task with args = '%s' and priority %d\n",
+ orbargs_,
+ prio));
+ int result = this->initialize_orb ();
+
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ORB initialization failed\n"),
+ -1);
+ result = this->create_servants ();
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Create Servants failed.\n"),
+ -1);
+
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ GLOBALS::instance ()->barrier_->wait ();
+
+ // Handle requests for this object until we're killed, or one of
+ // the methods asks us to exit.
+ int r = this->orb_manager_.run (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (r == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "run"),
+ -1);
+ ACE_TRY_CHECK;
+
+ CORBA::ORB_var orb =
+ this->orb_manager_.orb ();
+
+ orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "poa->destroy()");
+ }
+ ACE_ENDTRY;
+
+ // Need to clean up and do a CORBA::release on everything we've
+ // created!
+
+ for (u_int i = 0; i < num_of_objs_; i++)
+ delete this->servants_[i];
+
+ return 0;
+}
+
+int
+Cubit_Task::initialize_orb (void)
+{
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ ACE_ARGV args (this->orbargs_);
+
+ int argc = args.argc ();
+ char **argv = args.argv ();
+
+ char orb_name[BUFSIZ];
+ ACE_OS::sprintf (orb_name,
+ "ORB %d",
+ this->task_id_);
+
+ int r = this->orb_manager_.init_child_poa (argc,
+ argv,
+ "persistent_poa",
+ orb_name
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ if (r == -1)
+ return -1;
+
+ this->orb_ = this->orb_manager_.orb ();
+
+ // Do the argument parsing.
+ if (this->task_id_ == 0)
+ {
+ if (GLOBALS::instance ()->parse_args (argc,
+ argv) == -1)
+ return -1;
+ ACE_NEW_RETURN (GLOBALS::instance ()->barrier_,
+ ACE_Barrier (GLOBALS::instance ()->num_of_objs + 1),
+ -1);
+ ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ready_mon,
+ GLOBALS::instance ()->ready_mtx_, 1));
+ GLOBALS::instance ()->ready_ = 1;
+ GLOBALS::instance ()->ready_cnd_.broadcast ();
+ }
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "orb_init");
+ return -1;
+ }
+ ACE_ENDTRY;
+
+ return 0;
+}
+
+char*
+Cubit_Task::get_servant_ior (u_int index)
+{
+ if (index >= num_of_objs_)
+ return 0;
+ else
+ return ACE_OS::strdup (this->servants_iors_[index]);
+}
+
+int
+Cubit_Task::create_servants (void)
+{
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ CORBA::Object_var obj =
+ this->orb_->resolve_initial_references ("RootPOA"
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POA_var poa =
+ PortableServer::POA::_narrow (obj.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POAManager_var manager =
+ poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Create the array of cubit implementations.
+ ACE_NEW_RETURN (this->servants_,
+ Cubit_i *[this->num_of_objs_],
+ -1);
+
+ // Create the array of strings.
+ ACE_NEW_RETURN (this->servants_iors_,
+ char* [this->num_of_objs_],
+ -1);
+
+ char *buffer;
+ // Length of the string is the length of the key + 2 char id of
+ // the servant + null space.
+ int len = ACE_OS::strlen (this->key_) + 3;
+
+ ACE_NEW_RETURN (buffer,
+ char[len],
+ -1);
+
+ // This loop creates multiple servants, and prints out their
+ // IORs.
+ for (u_int i = 0;
+ i < this->num_of_objs_;
+ i++)
+ {
+ ACE_OS::sprintf (buffer,
+ "%s%02d",
+ this->key_,
+ this->task_id_);
+
+ ACE_NEW_RETURN (this->servants_[i],
+ Cubit_i (this->orb_.in (),
+ poa.in ()),
+ -1);
+
+ if (this->servants_[i] == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Unable to create "
+ "implementation object #%d\n",
+ i),
+ 2);
+
+ // Stringify the objref we'll be implementing, and print it
+ // to stdout. Someone will take that string and give it to
+ // some client. Then release the object.
+
+ Cubit_var cubit =
+ this->servants_[i]->_this (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+
+ CORBA::String_var str =
+ this->orb_->object_to_string (cubit.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ this->servants_iors_[i] =
+ ACE_OS::strdup (str.in ());
+ }
+
+ delete [] buffer;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Cubit_Task::create_servants");
+ return -1;
+ }
+ ACE_ENDTRY;
+ return 0;
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Cubit_Task.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Cubit_Task.h
new file mode 100644
index 00000000000..b222ad4c0b2
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Cubit_Task.h
@@ -0,0 +1,88 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// Cubit_Task.h
+//
+// = AUTHOR
+// Andy Gokhale, Sumedh Mungee,Sergio Flores-Gaitan and Nagarajan Surendran.
+//
+// ============================================================================
+
+#ifndef MT_CUBIT_TASK_H
+#define MT_CUBIT_TASK_H
+
+#include "ace/Task.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/ARGV.h"
+#include "tao/Utils/ORB_Manager.h"
+#include "cubit_i.h"
+#include "Globals.h"
+
+class Cubit_Task : public ACE_Task<ACE_SYNCH>
+{
+ // = TITLE
+ // Encapsulates an ORB for the Cubit application.
+public:
+ Cubit_Task (const char *args,
+ const char* orbname,
+ u_int num_of_objs,
+ ACE_Thread_Manager *thr_mgr,
+ u_int task_id);
+ // Constructor.
+
+ virtual int svc (void);
+ // Active Object entry point.
+
+ char* get_servant_ior (u_int index);
+ // Gets the ior of the cubit servant in this task.
+
+protected:
+ Cubit_Task (void);
+ // No-op constructor.
+
+private:
+ int initialize_orb (void);
+ // Initialize the ORB, and POA.
+
+ int create_servants (void);
+ // Create the servants.
+
+ const char *key_;
+ // All cubit objects will have this as prefix to its key.
+
+ char *orbname_;
+ // Name of the ORB.
+
+ char *orbargs_;
+ // ORB arguments.
+
+ u_int num_of_objs_;
+ // Number of objects we're managing.
+
+ CORBA::ORB_var orb_;
+ // Pointer to the ORB
+
+ Cubit_i **servants_;
+ // Array to hold the servants.
+
+ char **servants_iors_;
+ // IOR strings of the servants.
+
+ u_int task_id_;
+ // ID used for naming service object name.
+
+ TAO_ORB_Manager orb_manager_;
+ // The TAO ORB Manager.
+};
+
+#endif /* MT_CUBIT_TASK_H */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Globals.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Globals.cpp
new file mode 100644
index 00000000000..c8408545aac
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Globals.cpp
@@ -0,0 +1,227 @@
+// $Id$
+
+#include "Globals.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/Null_Mutex.h"
+
+Globals::Globals (void)
+ : thr_create_flags (0),
+ default_priority (0),
+ ior_file (0),
+ num_of_objs (2),
+ thread_per_rate (0),
+ use_multiple_priority (0),
+ ready_ (0),
+ ready_cnd_ (ready_mtx_),
+ barrier_ (0)
+{
+ const char default_endpoint[] = "iiop://";
+ // Default to iiop
+
+ ACE_OS::strcpy (endpoint, default_endpoint);
+}
+
+int
+Globals::parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt opts (argc, argv, "e:t:f:rm");
+ int c;
+
+ while ((c = opts ()) != -1)
+ {
+ switch (c)
+ {
+ case 'm':
+ use_multiple_priority = 1;
+ break;
+ case 'r':
+ thread_per_rate = 1;
+ break;
+ case 'f':
+ ACE_NEW_RETURN (ior_file,
+ char[BUFSIZ],
+ -1);
+ ACE_OS::strcpy (ior_file,
+ opts.opt_arg ());
+ break;
+ case 'e':
+ ACE_OS::strcpy (endpoint,
+ opts.opt_arg ());
+ break;
+ case 't':
+ num_of_objs = ACE_OS::atoi (opts.opt_arg ());
+ break;
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s \t"
+ "[-e <endpoint>] // starting endpoint \n\t\t\t"
+ "[-t <number_of_servants>] // # of servant threads to create \n\t\t\t"
+ "[-f <ior_file> ] // specify a file to output all ior's \n\t\t\t"
+ "[-m ] // Use multiple priorities for threads\n\t\t\t"
+ "[-r ] // Run the thread-per-rate test \n"
+ ,argv [0]),
+ -1);
+ }
+ }
+
+ if (thread_per_rate == 1)
+ num_of_objs = THREAD_PER_RATE_OBJS;
+
+ // Indicates successful parsing of the command-line.
+ return 0;
+}
+
+int
+Globals::sched_fifo_init (void)
+{
+#if defined (ACE_HAS_THREADS)
+ // Enable FIFO scheduling, e.g., RT scheduling class on Solaris.
+# if defined (_AIX) || defined (__APPLE__)
+ int scope = ACE_SCOPE_THREAD;
+# else
+ int scope = ACE_SCOPE_PROCESS;
+# endif /* _AIX */
+
+ if (ACE_OS::sched_params (ACE_Sched_Params (ACE_SCHED_FIFO,
+ SCHED_PRIORITY,
+ scope)))
+ {
+ if (ACE_OS::last_error () == EPERM)
+ {
+ ACE_DEBUG ((LM_MAX,
+ "User is not superuser, "
+ "so remain in time-sharing class\n"));
+ ACE_SET_BITS (GLOBALS::instance ()->thr_create_flags, THR_NEW_LWP);
+ GLOBALS::instance ()->default_priority = ACE_THR_PRI_OTHER_DEF;
+ return 1;
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%n: ACE_OS::sched_params failed\n%a"),
+ -1);
+ }
+
+ ACE_SET_BITS (GLOBALS::instance ()->thr_create_flags, THR_BOUND);
+ ACE_SET_BITS (GLOBALS::instance ()->thr_create_flags, THR_SCHED_FIFO);
+ GLOBALS::instance ()->default_priority = ACE_THR_PRI_FIFO_DEF;
+
+ return 0;
+#else
+
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Test will not run. This platform doesn't seem to have threads.\n"),
+ -1);
+#endif /* ACE_HAS_THREADS */
+}
+
+MT_Priority::MT_Priority (void)
+ : num_priorities_ (0),
+ grain_ (0)
+{
+}
+
+MT_Priority::~MT_Priority (void)
+{
+}
+
+ACE_Sched_Priority
+MT_Priority::get_high_priority (void)
+{
+ ACE_Sched_Priority high_priority;
+
+#if defined (VXWORKS)
+ high_priority = GLOBALS::instance ()->default_priority;
+#elif defined (ACE_WIN32)
+ high_priority =
+ ACE_Sched_Params::priority_max (ACE_SCHED_FIFO,
+ ACE_SCOPE_THREAD);
+#else
+ high_priority = GLOBALS::instance ()->default_priority;
+#endif /* VXWORKS */
+ return high_priority;
+}
+
+ACE_Sched_Priority
+MT_Priority::get_low_priority (u_int num_low_priority,
+ ACE_Sched_Priority prev_priority,
+ u_int use_multiple_priority)
+{
+#if !defined (ACE_HAS_THREADS)
+ ACE_UNUSED_ARG (num_low_priority);
+ ACE_UNUSED_ARG (prev_priority);
+ ACE_UNUSED_ARG (use_multiple_priority);
+ return -1;
+#else
+ ACE_Sched_Priority low_priority = ACE_THR_PRI_FIFO_DEF;
+ int policy = ACE_SCHED_FIFO;
+
+ if (!ACE_BIT_ENABLED (GLOBALS::instance ()->thr_create_flags,
+ THR_SCHED_FIFO))
+ {
+ low_priority = ACE_THR_PRI_OTHER_DEF;
+ policy = ACE_SCHED_OTHER;
+ }
+
+ // Drop the priority.
+ if (use_multiple_priority)
+ {
+ this->num_priorities_ = 0;
+
+ for (ACE_Sched_Priority_Iterator priority_iterator
+ (policy, ACE_SCOPE_THREAD);
+ priority_iterator.more ();
+ priority_iterator.next ())
+ this->num_priorities_++;
+
+ // 1 priority is exclusive for the high priority client.
+ this->num_priorities_--;
+
+ // Drop the priority, so that the priority of clients will
+ // increase with increasing client number.
+ for (u_int j = 0;
+ j < num_low_priority;
+ j++)
+ {
+ low_priority =
+ ACE_Sched_Params::previous_priority (policy,
+ prev_priority,
+ ACE_SCOPE_THREAD);
+ prev_priority = low_priority;
+ }
+ // Granularity of the assignment of the priorities. Some OSs
+ // have fewer levels of priorities than we have threads in our
+ // test, so with this mechanism we assign priorities to groups
+ // of threads when there are more threads than priorities.
+ this->grain_ = num_low_priority / this->num_priorities_;
+
+ if (this->grain_ <= 0)
+ this->grain_ = 1;
+ }
+ else
+ low_priority =
+ ACE_Sched_Params::previous_priority (policy,
+ prev_priority,
+ ACE_SCOPE_THREAD);
+ return low_priority;
+#endif /* ACE_HAS_THREADS */
+}
+
+u_int
+MT_Priority::number_of_priorities (void)
+{
+ return this->num_priorities_;
+}
+
+u_int
+MT_Priority::grain (void)
+{
+ return this->grain_;
+}
+
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<Globals, ACE_Null_Mutex> *ACE_Singleton<Globals, ACE_Null_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Globals.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Globals.h
new file mode 100644
index 00000000000..171458e98d7
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Globals.h
@@ -0,0 +1,219 @@
+// -*- C++ -*-
+// $Id$
+
+#ifndef GLOBALS_H
+#define GLOBALS_H
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// Globals.h
+//
+// = DESCRIPTION
+// All the globally defined classes, functions, types, and #defines
+// are centralized here.
+//
+// = AUTHOR
+// Nagarajan Surendran <naga@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Get_Opt.h"
+#include "ace/Sched_Params.h"
+#include "ace/Singleton.h"
+#include "ace/Condition_Thread_Mutex.h"
+
+#include "tao/orbconf.h"
+
+#if defined (VXWORKS) && defined (VME_DRIVER)
+#define VX_VME_INIT \
+STATUS status = vmeDrv ();\
+if (status != OK)\
+ ACE_DEBUG ((LM_DEBUG,\
+ "ERROR on call to vmeDrv()\n"));\
+ status = vmeDevCreate ("/vme");\
+ if (status != OK)\
+ ACE_DEBUG ((LM_DEBUG,\
+ "ERROR on call to vmeDevCreate()\n"));
+#else
+#define VX_VME_INIT
+#endif /* VXWORKS && VME_DRIVER */
+
+#if defined (__Lynx__)
+#define SCHED_PRIORITY 30
+#elif defined (VXWORKS)
+#define SCHED_PRIORITY 6
+#elif defined (ACE_WIN32) || defined (__FreeBSD__)
+#define SCHED_PRIORITY \
+ACE_Sched_Params::priority_max(ACE_SCHED_FIFO,ACE_SCOPE_THREAD)
+#elif defined (HPUX)
+#define SCHED_PRIORITY ACE_THR_PRI_FIFO_MAX
+#else
+#define SCHED_PRIORITY \
+ACE_THR_PRI_FIFO_DEF + 25
+#endif /* ! __Lynx__ */
+
+#if defined (CHORUS_MVME)
+#define PCCTIMER_INIT {int pTime;/*Initialize the PCC timer chip */pccTimerInit ();\
+if (pccTimer (PCC2_TIMER1_START, &pTime) != K_OK)\
+ACE_DEBUG ((LM_DEBUG,"pccTimer has a pending benchmark\n"));\
+}
+#else /* !CHORUS_MVME */
+#define PCCTIMER_INIT
+#endif /* !CHORUS_MVME */
+
+#if defined (VXWORKS) && defined (FORCE_ARGS)
+static char *force_argv[]=
+{
+ "server",
+ "-f",
+ "ior.txt"
+};
+#endif /* defined (VXWORKS) && defined (FORCE_ARGS) */
+
+#if defined (VXWORKS) && defined (FORCE_ARGS)
+#define FORCE_ARGV(argc,argv) \
+argc = 4;
+argv = force_argv;
+#else /* !VXWORKS && !FORCE_ARGS */
+#define FORCE_ARGV(argc,argv)
+#endif
+// Number of utilisation computations to compute the duration of one
+// util computation.
+#define NUM_UTIL_COMPUTATIONS 10000
+
+#define THREAD_PER_RATE_OBJS 4
+// Number of cubit objects in the thread per rate test.
+
+#define TASK_ID_LEN 32
+// length of the task id ,used in vxworks.
+
+#define TASKNAME_LEN 14
+// Length of the task name in the task control block for vxworks.
+
+#define UTIL_BOUND_CONSTANT 1000
+// A constant to avoid the utility thread blocking the machine and to
+// bound its number of computations.
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_Barrier;
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+class Globals
+{
+ // = TITLE
+ // Globals class to be used as a singleton.
+ //
+ // = DESCRIPTION
+ // This is used both by the server and client.
+public:
+ Globals (void);
+ // default constructor.
+
+ int parse_args (int argc, char **argv);
+ // parse the arguments.
+
+ static int sched_fifo_init (void);
+ // Enables fifo scheduling eg., RT scheduling class on solaris.
+ // Returns 0 on success, 1 if insufficient permission, or -1
+ // for other failure. As a side effect, sets thr_create_flags
+ // appropriately.
+
+ long thr_create_flags;
+ // Thread creation flags. Must call sched_fifo_init () before
+ // accessing.
+
+ int default_priority;
+ // Default thread priority, used for the high thread priority.
+ // Must call sched_fifo_init () before accessing.
+
+ char endpoint[BUFSIZ];
+ // endpoint to be used for ORB_init.
+
+ char *ior_file;
+ // file name to read/write the iors of the servants.
+
+ u_int num_of_objs;
+ // number of objects per servant thread.
+
+ u_int thread_per_rate;
+ // thread_per_rate test flag.
+
+ u_int use_multiple_priority;
+ // flag to use multiple priorities for the low priority servants
+ // instead of one priority.
+
+ int ready_;
+ // ready flag used by the high priority thread to wake up the low
+ // priority threads after it's parsed the arguments.
+
+ TAO_SYNCH_MUTEX ready_mtx_;
+ // mutex for the condition variable.
+
+ TAO_SYNCH_CONDITION ready_cnd_;
+ // condition variable for the low priority threads to wait
+ //until the high priority thread is done with the arguments parsing.
+
+ ACE_Barrier *barrier_;
+ // Barrier for the multiple servants to synchronize after binding to
+ // the orb.
+};
+
+// Make the globals a Singleton.
+typedef ACE_Singleton<Globals,ACE_Null_Mutex> GLOBALS;
+
+class MT_Priority
+{
+ // = TITLE
+ // Helper class to find high and low priorities for the
+ // MT_Cubit application over multiple platforms.
+ //
+ // = DESCRIPTION
+ // This class has 2 methods, one for the high priority and the
+ // other for low priority.If the flag use_multiple_priority is
+ // passed then multiple priorities are used for the low priority
+ // threads.
+
+public:
+ MT_Priority (void);
+ // constructor.
+
+ /// Destructor.
+ virtual ~MT_Priority (void);
+
+ virtual ACE_Sched_Priority get_high_priority (void);
+ // Sets the priority of the high priority thread.
+
+ virtual ACE_Sched_Priority get_low_priority
+ (u_int num_low_priority,
+ ACE_Sched_Priority prev_priority,
+ u_int use_multiple_priority);
+ // Sets the priority to be used for the low priority thread.
+
+ u_int number_of_priorities (void);
+ // Accessor for num_priorities_.
+
+ u_int grain (void);
+ // Accessor for grain_.
+
+protected:
+ u_int num_priorities_;
+ // Number of priorities used.
+
+ u_int grain_;
+ // Granularity of the assignment of the priorities. Some OSs have
+ // fewer levels of priorities than we have threads in our test, so
+ // with this mechanism we assign priorities to groups of threads
+ // when there are more threads than priorities.
+};
+
+#endif /* GLOBALS_H */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/MT_Cubit.mpc b/TAO/performance-tests/Cubit/TAO/MT_Cubit/MT_Cubit.mpc
new file mode 100644
index 00000000000..d5cc27cdc06
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/MT_Cubit.mpc
@@ -0,0 +1,49 @@
+// -*- MPC -*-
+// $Id$
+
+project(*IDL): taoidldefaults, strategies {
+ IDL_Files {
+ cubit.idl
+ }
+ custom_only = 1
+}
+
+project(*server): taoexe, utils, portableserver, strategies {
+ after += *IDL
+
+ Source_Files {
+ Timer.cpp
+ Cubit_Task.cpp
+ Globals.cpp
+ cubit_i.cpp
+ server.cpp
+ cubitS.cpp
+ cubitC.cpp
+ }
+
+ IDL_Files {
+ }
+}
+
+project(*client): taoexe, utils, portableserver, strategies {
+ after += *IDL
+
+ Source_Files {
+ Timer.cpp
+ Globals.cpp
+ cubit_i.cpp
+ Cubit_Task.cpp
+ Util_Thread.cpp
+ Task_Client.cpp
+ client.cpp
+ cubitS.cpp
+ cubitC.cpp
+ }
+
+ IDL_Files {
+ }
+
+ verbatim(gnuace, local) {
+ LDLIBS += $(MATHLIB)
+ }
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/MT_Cubit_Test b/TAO/performance-tests/Cubit/TAO/MT_Cubit/MT_Cubit_Test
new file mode 100755
index 00000000000..e52dd38cece
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/MT_Cubit_Test
@@ -0,0 +1,102 @@
+#! /bin/sh
+# $Id$
+#
+# Spawns MT_Cubit server and client executables on a single host.
+
+usage="usage: $0 [-n <iterations>] [-r <host>] [-t] [-l] <# low priority threads>"
+usage2=" [-l] suppresses use of -ORBgioplite, [-r runs client on <host>], [-t] uses /tmp"
+
+user=`whoami`
+ior_file=/tmp/MT_Cubit-ior.${user}
+iterations=1000
+client_exec_prefix=time
+gioplite=-ORBgioplite
+remote_host=
+
+if [ "$HOSTTYPE" = "lynxos" ]; then
+ server_exec_prefix='prio 30'
+ tmp='/tmp/'
+else
+ server_exec_prefix=
+ tmp=
+fi
+
+if [ ! "$PWD" ]; then
+ PWD=`pwd`
+fi
+
+########
+######## Interpret command arguments.
+########
+while getopts ?ln:r:t arg; do
+ case $arg in
+ l ) gioplite= ;;
+ n ) iterations=$OPTARG ;;
+ r ) remote_host=$OPTARG
+ ior_file=MT_Cubit-ior ;;
+ t ) tmp='/tmp/' ;;
+ '?' ) echo $usage; echo $usage2; exit 0 ;;
+ esac
+done
+
+if [ "$OPTIND" ]; then
+ shift `expr $OPTIND - 1`
+
+ if [ $# -ne 1 ]; then
+ echo $usage; echo $usage2
+ exit 1
+ fi
+else
+ #### sh does not support $OPTIND. Arg error checking isn't as good.
+ if [ $# -lt 1 ]; then
+ echo $usage; echo $usage2
+ exit 1
+ fi
+
+ shift `expr $# - 1`
+fi
+
+threads=`expr $1 + 1`
+
+
+########
+######## Make sure that the executables have been built.
+########
+if [ ! -f ./server -o ! -f ./client ]; then
+ echo $0: 'server and/or client need to be built!'
+ exit -1
+fi
+
+
+########
+######## Enable signal handler.
+########
+trap 'kill -15 $server_pid; /bin/rm -f $ior_file; exit 0' 0 1 2 15
+
+
+########
+######## Start server and save its pid.
+########
+/bin/rm -f $ior_file
+$server_exec_prefix ./server -f $ior_file -t $threads $gioplite > \
+ ${tmp}server.log 2>&1 &
+server_pid=$!
+
+while [ ! -f $ior_file ]; do
+ sleep 2
+done
+
+
+########
+######## Start client.
+########
+if [ "$remote_host" ]; then
+ rsh $remote_host \
+ "cd $PWD; LD_LIBRARY_PATH=$LD_LIBRARY_PATH $client_exec_prefix \
+ ./client -f $ior_file -t $threads -n $iterations $gioplite" > \
+ ${tmp}client-${threads}.log 2>&1
+else
+ $client_exec_prefix \
+ ./client -f $ior_file -t $threads -n $iterations $gioplite > \
+ ${tmp}client-${threads}.log 2>&1
+fi
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile.am b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile.am
new file mode 100644
index 00000000000..bad37120f93
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Makefile.am
@@ -0,0 +1,140 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## ../bin/mwc.pl -type automake -noreldefs TAO.mwc
+
+ACE_BUILDDIR = $(top_builddir)/..
+ACE_ROOT = $(top_srcdir)/..
+TAO_BUILDDIR = $(top_builddir)
+TAO_IDL = ACE_ROOT=$(ACE_ROOT) TAO_ROOT=$(TAO_ROOT) $(TAO_BUILDDIR)/TAO_IDL/tao_idl
+TAO_IDL_DEP = $(TAO_BUILDDIR)/TAO_IDL/tao_idl
+TAO_IDLFLAGS = -Ge 1 -Wb,pre_include=ace/pre.h -Wb,post_include=ace/post.h -I$(TAO_ROOT) -I$(srcdir) -g $(ACE_BUILDDIR)/apps/gperf/src/gperf
+TAO_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.MT_Cubit_IDL.am
+
+if !BUILD_ACE_FOR_TAO
+
+BUILT_SOURCES = \
+ cubitC.cpp \
+ cubitC.h \
+ cubitC.inl \
+ cubitS.cpp \
+ cubitS.h \
+ cubitS.inl
+
+CLEANFILES = \
+ cubit-stamp \
+ cubitC.cpp \
+ cubitC.h \
+ cubitC.inl \
+ cubitS.cpp \
+ cubitS.h \
+ cubitS.inl
+
+cubitC.cpp cubitC.h cubitC.inl cubitS.cpp cubitS.h cubitS.inl: cubit-stamp
+
+cubit-stamp: $(srcdir)/cubit.idl $(TAO_IDL_DEP)
+ $(TAO_IDL) $(TAO_IDLFLAGS) $(srcdir)/cubit.idl
+ @touch $@
+
+
+noinst_HEADERS = \
+ cubit.idl
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.MT_Cubit_Client.am
+
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS += client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -I$(TAO_ROOT) \
+ -I$(TAO_BUILDDIR)
+
+client_SOURCES = \
+ Cubit_Task.cpp \
+ Globals.cpp \
+ Task_Client.cpp \
+ Timer.cpp \
+ Util_Thread.cpp \
+ client.cpp \
+ cubitC.cpp \
+ cubitS.cpp \
+ cubit_i.cpp \
+ Cubit_Task.h \
+ Globals.h \
+ Task_Client.h \
+ Timer.h \
+ Util_Thread.h \
+ client.h \
+ cubit_i.h
+
+client_LDADD = \
+ $(TAO_BUILDDIR)/tao/libTAO_Strategies.la \
+ $(TAO_BUILDDIR)/tao/libTAO_Utils.la \
+ $(TAO_BUILDDIR)/tao/libTAO_PI.la \
+ $(TAO_BUILDDIR)/tao/libTAO_CodecFactory.la \
+ $(TAO_BUILDDIR)/tao/libTAO_PortableServer.la \
+ $(TAO_BUILDDIR)/tao/libTAO_AnyTypeCode.la \
+ $(TAO_BUILDDIR)/tao/libTAO.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.MT_Cubit_Server.am
+
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS += server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -I$(TAO_ROOT) \
+ -I$(TAO_BUILDDIR)
+
+server_SOURCES = \
+ Cubit_Task.cpp \
+ Globals.cpp \
+ Timer.cpp \
+ cubitC.cpp \
+ cubitS.cpp \
+ cubit_i.cpp \
+ server.cpp \
+ Cubit_Task.h \
+ Globals.h \
+ Timer.h \
+ cubit_i.h \
+ server.h
+
+server_LDADD = \
+ $(TAO_BUILDDIR)/tao/libTAO_Strategies.la \
+ $(TAO_BUILDDIR)/tao/libTAO_Utils.la \
+ $(TAO_BUILDDIR)/tao/libTAO_PI.la \
+ $(TAO_BUILDDIR)/tao/libTAO_CodecFactory.la \
+ $(TAO_BUILDDIR)/tao/libTAO_PortableServer.la \
+ $(TAO_BUILDDIR)/tao/libTAO_AnyTypeCode.la \
+ $(TAO_BUILDDIR)/tao/libTAO.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/README b/TAO/performance-tests/Cubit/TAO/MT_Cubit/README
new file mode 100644
index 00000000000..6a9a0ff666c
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/README
@@ -0,0 +1,215 @@
+// $Id$
+
+THE MT_CUBIT EXAMPLE
+--------------------
+
+This directory contains the source code for the TAO "MT_Cubit"
+benchmark, which enables us to measure the real-time performance of
+TAO. MT_Cubit measures the latency, jitter, determinism, CPU
+utilization, and degree of priority inversion incurred by TAO twoway
+operations invoked under different workloads and priorities. For
+more information and empirical results, please see
+
+http://www.cs.wustl.edu/~schmidt/PDF/RT-perf.pdf
+http://www.cs.wustl.edu/~schmidt/PDF/RT-OS.pdf
+
+COMPILING
+---------
+
+Makefile is provided. Use make to compile.
+
+You can either run the server in the background in the same window as
+the client or open a separate window for the client and server.
+
+OPTIONS
+-------
+Options are case sensitive, e.g., "-U" has a different meaning than "-u".
+
+(1) server:
+
+./server [-e <endpoint>] // Endpoint to use (URL style endpoint)
+ [-t <number_of_servants>] // # of servant threads to create
+ [-f <ior_file> ] // specify a file to output all ior's
+ [-m ] // Use multiple priorities for threads
+ [-r ] // Run the thread-per-rate test
+
+[-e <endpoint>] indicates the endpoint the ORB should bind to.
+ This is useful when a machine has more than one network interface.
+
+ Default Value: Whatever the current active pluggable protocol
+ uses as its default endpoint.
+
+[-t <number_of_servants>] tells the server how many servants to create.
+
+ Default Value: 2
+
+[-f <ior_file> ] Use to specify a file to write all the iors from the
+ different servants out to disk.
+
+ Default Value: nil, which means not to write the iors to disk.
+
+[-m ] For the 1 to n low priority servants, this parameter indicates
+ the use of a range of priorities for the threads.
+
+ Default Value: Disabled. One priority will be used for the
+ low priority threads.
+
+[-r] turn on the thread-per-rate tests. (Priority inversion tests)
+
+ Default Value: Disabled.
+
+The server will print the IOR of the servants, but it is not required
+by the client.
+
+(2) client:
+
+./client [<ORB OPTIONS>] // ORB options, e.g., "-ORBObjRefStyle url"
+ [-d <datatype>] // what datatype to use for calls
+ [-n <num_calls>] // number of CORBA calls to make.
+ [-t <num_of_clients>] // number of client threads to create
+ [-f <ior_file>] // specify the file from which we read the object references (iors), if any.
+ [-r] // run thread-per-rate test.
+ [-o] // makes client use oneway calls. By default, twoway calls are used.
+ [-x] // makes a call to servant to shutdown
+ [-u <requests> ] // run the client utilization test for a number of <requests>.
+ [-1] // run the one-to-n test.
+ [-g <granularity>] // choose the granularity of the timing of CORBA calls
+ [-c] // run the number of context switches test.
+ [-m] // use multiple priorities for the low priority clients.
+
+[-d <datatype>] <datatype> is one of the following:
+
+ 0 Octet
+ 1 Short
+ 2 Long
+ 3 Struct of the above 3 types
+
+ Default Value: 0
+
+[-n <num_calls>] is the number of CORBA twoway calls to be made
+
+ Default Value: 1000
+
+[-t <num_of_clients>] is the total number of concurrent clients to be
+ created. The clients will have successively decreasing
+ priorities if "-m" is specified.
+
+ Default Value: 2
+
+[-f <ior_file> ] Use to specify a file to read the object references (iors) of the
+ different servants from disk.
+
+ Default Value: nil, which means not to read the iors from disk.
+
+[-r] run the thread-per-rate test. (Priority inversion tests)
+
+ Default Value: Disabled.
+
+[-o] enables oneway calls instead of two-way calls. The oneway call
+ is a noop call (for now).
+
+ Default Value: Disabled
+
+[-x] makes the client call the shutdown() method on the servant which in turn
+ invokes the shutdown() method on the ORB and causes it to exit gracefully.
+
+ Default Value: Disabled
+
+[-u <seconds>] runs the client/server utilization test for a number of <requests>.
+ The output is the number of seconds for the test to make such number of requests.
+ Now run the same test but with the -l option to make the same number of requests,
+ this time not using CORBA, instead directly making function calls. The difference
+ in time for each test to make the same number of requests is the utilization of
+ the OS/ORB combined.
+ (Note: This option overrides any specified "-t" option)
+
+ Default Value: Disabled
+
+[-1] runs one-to-n test. One servant services all low priority clients.
+
+ Default Value: Disabled
+
+[-g <granularity>] choose the granularity of timing the CORBA calls.
+ This option should disappear sometime in the future, together with
+ all the modifications done to support this.
+
+ What happens when this options is not used, is that (1) we start a
+ timer, (2) invoke the CORBA call, (3) stop the timer after call
+ returns. Some platforms have a very coarse grain timer (e.g. 10
+ msec) and timing individual calls does not report very accurate
+ latency results.
+
+ This option enables a way to (1) start the timer, (2) invoke
+ <granularity> calls, and (3) stop the timer. This way, we get a
+ better sense of the average latency of the CORBA calls.
+
+ The downside is that the mechanism to enforce the frequency of calls
+ (i.e., 20 Hz, 10Hz, etc) is in conflict with this option. Such
+ mechanism depends on the individual time for each call to enforce
+ the calling frequency.
+
+ Default Value: 1 (time each CORBA call)
+
+[-c] Obtain number of context switches.
+
+ Default Value: Disabled
+
+[-m] Use multiple priorities for the low priority client
+
+ Default Value: Disabled. Will use one priority for all low priority clients.
+
+Running on VxWorks
+------------------
+
+A typical run of the server and client on a single VxWorks target:
+
+ -> iam "<your login>"
+ -> ld < server
+ -> ld < client
+ -> spa server, "-f", "ior.txt", "-t", "2"
+ -> spa client, "-f", "ior.txt", "-t", "2", "-n", "1000"
+
+RESULTS
+-------
+
+The client prints the latency observed by the high priority client,
+and the average latency observed by the low priority clients. Jitter
+(standard deviation of the latency) is also printed by the client.
+
+
+Running MT_Cubit on CHORUS:
+--------------------------
+
+1.You should make sure that you set the HOST environment variable on the
+Chorus VME Board to the IP address of that Board before you run
+MT_Cubit test.
+
+e.g
+$rsh tambora1 setenv HOST 128.252.165.82
+
+2. You should make sure that the path to IOR file has write permission
+for ALL.
+
+server:
+------
+$rsh host_name arun path_to_server -e iiop://DOTTED_DECIMAL_ADDRESS:0
+ -f path_to_ior_file -ORBDottedDecimalAddresses 1 <server_options>
+
+Since Chorus doesn't support DNS, you should pass
+dotted_decimal_address of the server machine to -e option.
+
+You DONT have to use -ORBDottedDecimalAddresses 1 if you have
+TAO_USE_DOTTED_DECIMAL_ADDRESSES defined in your config.h file.
+
+e.g
+$rsh tambora1 arun /MT_Cubit/server -e iiop://128.252.165.82:0 -f /ior
+-ORBDottedDecimalAddresses 1 -t 10 -ORBObjRefStyle url
+
+client:
+-------
+
+$rsh host_name arun path_to_client -f path_to_ior_file <client_options>
+
+e.g
+
+$rsh tambora2 arun /MT_Cubit/client -f /ior -t 10 -n 300
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/README.tests b/TAO/performance-tests/Cubit/TAO/MT_Cubit/README.tests
new file mode 100644
index 00000000000..c81387596f6
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/README.tests
@@ -0,0 +1,44 @@
+// $Id$
+
+Note: this file is in very rough version. Updates are coming soon.
+
+ORB/OS CPU processing Overhead Test
+-----------------------
+1. Execute the following command to obtain latency for CORBA requests:
+
+ ./client -u 10000000
+
+NOTE: This runs a copy of the server in the same process as the client
+and executes 10,000,000 CORBA requests. Take a note of the total latency (L1).
+
+2. Execute the following command to obtain latency for collocated calls:
+
+ ./client -u 10000000 -l
+
+NOTE: The total latency is L2.
+
+The percentage of overhead is calculated in the following way:
+
+% Overhead = ( (L1 - L2) / L1 ) * 100
+
+
+Latency Test
+------------------------
+-- configuration:
+ (1) su to root when running Solaris or LynxOS.
+ (2) Make yourself an Administrator in Windows NT
+
+on the server side:
+ ./server -f ior -t 2 &
+on the client side:
+ ./client -f ior -t 2 -n 4000 -x
+
+NOTE: run_same is a script that automates the running of the latency
+tests. This script output everything to a file.
+
+Context Switch Test
+-------------------
+Use the same arguments as the latency test, and add "-c"
+
+NOTE: For Windows NT use a tool like Microsoft Spy that is installed with
+MS Visual C++ to obtain the context switch data.
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp
new file mode 100644
index 00000000000..876035b66dc
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.cpp
@@ -0,0 +1,1147 @@
+// $Id$
+
+#include "Task_Client.h"
+#include "Timer.h"
+#include "ace/Stats.h"
+#include "tao/TAO_Internal.h"
+#include "ace/Barrier.h"
+#include "ace/Thread_Semaphore.h"
+#include "ace/OS_NS_unistd.h"
+
+#if defined (ACE_HAS_QUANTIFY)
+# include "quantify.h"
+#endif /* ACE_HAS_QUANTIFY */
+
+inline
+ACE_UINT32
+ACE_round (ACE_timer_t t)
+{
+#if defined (ACE_LACKS_FLOATING_POINT)
+ return t;
+#else
+ return static_cast<ACE_UINT32> (t);
+#endif
+}
+
+ACE_RCSID(MT_Cubit, Task_Client, "$Id$")
+
+Task_State::Task_State (void)
+ : barrier_ (0),
+ key_ ("Cubit"),
+ loop_count_ (1000),
+ thread_count_ (2),
+ latency_ (0),
+ ave_latency_ (0),
+ datatype_ (CB_OCTET),
+ thread_per_rate_ (0),
+ global_jitter_array_ (0),
+ count_ (0),
+ shutdown_ (0),
+ oneway_ (0),
+ one_ior_ (0),
+ one_to_n_test_ (0),
+ context_switch_test_ (0),
+ iors_ (0),
+ iors_count_ (0),
+ ior_file_ (0),
+ granularity_ (1),
+ use_utilization_test_ (0),
+ high_priority_loop_count_ (0),
+ semaphore_ (0),
+ use_multiple_priority_ (0),
+ ready_ (0),
+ ready_cnd_ (ready_mtx_),
+ remote_invocations_ (1),
+ util_test_time_ (0)
+{
+}
+
+int
+Task_State::parse_args (int argc,char *argv[])
+{
+ ACE_Get_Opt opts (argc, argv, "mu:n:t:d:rxof:g:1cl");
+ int c;
+
+ while ((c = opts ()) != -1)
+ switch (c) {
+ case 'g':
+ granularity_ = ACE_OS::atoi (opts.opt_arg ());
+ if (granularity_ < 1)
+ granularity_ = 1;
+ break;
+ case 'l':
+ remote_invocations_ = 0;
+ break;
+ case 'c':
+ context_switch_test_ = 1;
+ break;
+ case 'm':
+ use_multiple_priority_ = 1;
+ break;
+ case '1':
+ one_to_n_test_ = 1;
+ break;
+ case 'u':
+ use_utilization_test_ = 1;
+ loop_count_ = ACE_OS::atoi (opts.opt_arg ());
+ break;
+ case 'f':
+ ior_file_ = ACE_OS::strdup (opts.opt_arg ());
+ break;
+ case 'o':
+ oneway_ = 1;
+ break;
+ case 'x':
+ shutdown_ = 1;
+ break;
+ case 'r':
+ thread_per_rate_ = 1;
+ break;
+ case 'd':
+ {
+ int datatype = ACE_OS::atoi (opts.opt_arg ());
+ switch (datatype)
+ {
+ case CB_OCTET:
+ ACE_DEBUG ((LM_DEBUG,
+ "Testing Octets\n"));
+ datatype_ = CB_OCTET;
+ break;
+ case CB_LONG:
+ ACE_DEBUG ((LM_DEBUG,
+ "Testing Longs\n"));
+ datatype_ = CB_LONG;
+ break;
+ case CB_STRUCT:
+ ACE_DEBUG ((LM_DEBUG,
+ "Testing Structs\n"));
+ datatype_ = CB_STRUCT;
+ break;
+ case CB_SHORT:
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ "Testing Shorts\n"));
+ datatype_ = CB_SHORT;
+ break;
+ }
+ }
+ continue;
+ case 'n': // loop count
+ loop_count_ = (u_int) ACE_OS::atoi (opts.opt_arg ());
+ continue;
+ case 't':
+ thread_count_ = (u_int) ACE_OS::atoi (opts.opt_arg ());
+ continue;
+ case '?':
+ default:
+ ACE_DEBUG ((LM_DEBUG, "usage: %s\t"
+ "[<ORB OPTIONS>] // ORB options, e.g., \"-ORBobjrefstyle url\" \n\t\t\t"
+ "[-d <datatype>] // what datatype to use for calls: Octet=0, Short=1, Long=2, Struct=3 \n\t\t\t"
+ "[-n <num_calls>] // number of CORBA calls to make. \n\t\t\t"
+ "[-t <num_of_clients>] // number of client threads to create \n\t\t\t"
+ "[-f <ior_file>] // specify the file from which we read the object references (iors), if any.\n\t\t\t"
+ "[-r] // run thread-per-rate test. \n\t\t\t"
+ "[-o] // makes client use oneway calls. By default, twoway calls are used. \n\t\t\t"
+ "[-x] // makes a call to servant to shutdown \n\t\t\t"
+ "[-u <requests> ] // run the client utilization test for a number of <requests> \n\t\t\t"
+ "[-1] // run the one-to-n test. \n\t\t\t"
+ "[-g <granularity>] // choose the granularity of the timing of CORBA calls \n\t\t\t"
+ "[-c] // run the number of context switches test. \n\t\t\t"
+ "[-l] // use direct function calls, as opposed to CORBA requests. ONLY to be used with -u option.\n\t\t\t"
+ "[-m] // use multiple priorities for the low priority clients. \n"
+ ,argv [0]));
+ return -1;
+ }
+
+ if (thread_per_rate_ == 1)
+ thread_count_ = THREAD_PER_RATE_OBJS;
+
+ if (use_utilization_test_ == 1)
+ {
+ thread_count_ = 1;
+ shutdown_ = 1;
+ datatype_ = CB_OCTET;
+ }
+
+ // Allocate the array of character pointers.
+ ACE_NEW_RETURN (iors_,
+ char *[thread_count_],
+ -1);
+
+ if (ior_file_ != 0)
+ {
+ FILE *ior_file =
+ ACE_OS::fopen (ior_file_, "r");
+
+ if (ior_file == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Task_State::parse_args; "
+ "unable to open IOR file \"%s\"\n",
+ ior_file_),
+ -1);
+ char buf[BUFSIZ];
+ u_int i;
+
+ for (i = 0;
+ ACE_OS::fgets (buf, BUFSIZ, ior_file) != 0
+ && i < thread_count_;
+ i++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ buf));
+ int j = ACE_OS::strlen (buf);
+
+ // This overwrites the '\n' that was read from the file.
+ buf[j - 1] = 0;
+ iors_[i] = ACE_OS::strdup (buf);
+ }
+
+ this->iors_count_ = i;
+ ACE_OS::fclose (ior_file);
+ }
+
+ // thread_count_ + 2 because there is one utilization thread also
+ // wanting to begin at the same time the clients begin && the main
+ // thread wants to know when clients will start running to get
+ // accurate context switch numbers.
+
+ if (thread_per_rate_ == 0)
+ {
+ if (use_utilization_test_ == 1)
+ // If we are to use the utilization test, include it in the
+ // barrier count. See description of this variable in header
+ // file.
+ ACE_NEW_RETURN (barrier_,
+ ACE_Barrier (thread_count_ + 2),
+ -1);
+ else
+ ACE_NEW_RETURN (barrier_,
+ ACE_Barrier (thread_count_ + 1),
+ -1);
+ }
+ else
+ ACE_NEW_RETURN (this->barrier_,
+ ACE_Barrier (thread_count_),
+ -1);
+ ACE_NEW_RETURN (this->semaphore_,
+ ACE_SYNCH_SEMAPHORE (0),
+ -1);
+ ACE_NEW_RETURN (this->latency_,
+ ACE_timer_t [thread_count_],
+ -1);
+ ACE_NEW_RETURN (this->global_jitter_array_,
+ JITTER_ARRAY *[this->thread_count_],
+ -1);
+ ACE_NEW_RETURN (this->count_,
+ u_int [thread_count_],
+ -1);
+ return 0;
+}
+
+Task_State::~Task_State (void)
+{
+ int i;
+
+ if (this->ior_file_ != 0)
+ ACE_OS::free (this->ior_file_);
+
+ // Delete the strduped memory.
+ for (i = 0; i < this->iors_count_; i++)
+ ACE_OS::free (this->iors_ [i]);
+
+ delete [] this->iors_;
+ // Delete the barrier.
+
+ delete this->barrier_;
+ delete this->semaphore_;
+ delete [] this->latency_;
+ delete [] this->ave_latency_;
+ delete [] this->global_jitter_array_;
+ delete [] this->count_;
+}
+
+Client::Client (ACE_Thread_Manager *thread_manager,
+ Task_State *ts,
+ int argc,
+ char **argv,
+ u_int id)
+ : ACE_Task<ACE_SYNCH> (thread_manager),
+ cubit_impl_ (CORBA::ORB::_nil (),
+ PortableServer::POA::_nil ()),
+ ts_ (ts),
+ num_ (0),
+ id_ (id),
+ call_count_ (0),
+ error_count_ (0),
+ my_jitter_array_ (0),
+ timer_ (0),
+ frequency_ (0),
+ latency_ (0),
+ argc_ (argc),
+ argv_ (argv)
+{
+}
+
+Client::~Client (void)
+{
+ delete this->my_jitter_array_;
+ delete this->timer_;
+}
+
+int
+Client::func (u_int i)
+{
+ return i - 117;
+}
+
+void
+Client::put_latency (JITTER_ARRAY *jitter,
+ ACE_timer_t latency,
+ u_int thread_id,
+ u_int count)
+{
+ ACE_MT (ACE_GUARD (TAO_SYNCH_MUTEX, ace_mon, this->ts_->lock_));
+
+ this->ts_->latency_[thread_id] = latency;
+ this->ts_->global_jitter_array_[thread_id] = jitter;
+ this->ts_->count_[thread_id] = count;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) My latency was %A msec\n",
+ latency/ACE_ONE_SECOND_IN_MSECS));
+}
+
+// Returns the latency in usecs.
+ACE_timer_t
+Client::get_high_priority_latency (void)
+{
+ return (ACE_timer_t) this->ts_->latency_ [0];
+}
+
+// Returns the latency in usecs.
+ACE_timer_t
+Client::get_low_priority_latency (void)
+{
+ if (this->ts_->thread_count_ == 1)
+ return 0;
+
+ ACE_timer_t l = 0;
+
+ for (u_int i = 1;
+ i < this->ts_->thread_count_;
+ i++)
+ l += (ACE_timer_t) this->ts_->latency_[i];
+
+ // Return the average latency for the low priority threads.
+ return l / (ACE_timer_t) (this->ts_->thread_count_ - 1);
+}
+
+ACE_timer_t
+Client::get_latency (u_int thread_id)
+{
+ return static_cast<ACE_timer_t> (this->ts_->latency_ [thread_id]);
+}
+
+// Returns the jitter in usecs.
+ACE_timer_t
+Client::get_high_priority_jitter (void)
+{
+ ACE_timer_t jitter = 0.0;
+ ACE_timer_t average = get_high_priority_latency ();
+ u_int number_of_samples = 0;
+
+ // Compute the standard deviation, i.e., jitter, from the values
+ // stored in the global_jitter_array_.
+
+ ACE_Stats stats;
+
+ // We first compute the sum of the squares of the differences each
+ // latency has from the average.
+
+ JITTER_ARRAY_ITERATOR iterator =
+ this->ts_->global_jitter_array_[0]->begin ();
+
+ // latency in usecs.
+ ACE_timer_t *latency = 0;
+
+ for (iterator.first ();
+ iterator.next (latency) == 1;
+ iterator.advance ())
+ {
+ ++number_of_samples;
+
+ ACE_timer_t difference = *latency - average;
+ jitter += difference * difference;
+
+ if (stats.sample (ACE_round (*latency)) == -1)
+ ACE_DEBUG ((LM_DEBUG, "Error: stats.sample returned -1\n"));
+
+ }
+
+ // Return the square root of the sum of the differences computed
+ // above, i.e., jitter.
+
+ ACE_DEBUG ((LM_DEBUG,
+ "high priority jitter (%u samples):\n", number_of_samples));
+
+ ACE_DEBUG ((LM_DEBUG,"Latency stats (time in usec)\n"));
+ stats.print_summary (1, 1, stderr);
+
+ return sqrt (jitter / (number_of_samples - 1));
+}
+
+// Returns the jitter in usecs.
+
+ACE_timer_t
+Client::get_low_priority_jitter (void)
+{
+ if (this->ts_->thread_count_ == 1)
+ return 0;
+
+ ACE_timer_t jitter = 0.0;
+ ACE_timer_t average = get_low_priority_latency ();
+ u_int number_of_samples = 0;
+
+ // Compute the standard deviation, i.e., jitter, from the values
+ // stored in the global_jitter_array_.
+
+ ACE_Stats stats;
+
+ // We first compute the sum of the squares of the differences each
+ // latency has from the average.
+
+ for (u_int j = 1;
+ j < this->ts_->thread_count_;
+ j++)
+ {
+ ACE_DEBUG ((LM_DEBUG, "count: %u\n", ts_->count_[j]));
+
+ JITTER_ARRAY_ITERATOR iterator =
+ this->ts_->global_jitter_array_ [j]->begin ();
+
+ ACE_timer_t number_of_calls =
+ this->ts_->count_ [j] / this->ts_->granularity_;
+
+ ACE_timer_t *latency = 0;
+
+ u_int i = 0;
+
+ for (iterator.first ();
+ i < number_of_calls && iterator.next (latency) == 1;
+ iterator.advance ())
+ {
+ ++number_of_samples;
+ ACE_timer_t difference = *latency - average;
+ jitter += difference * difference;
+ stats.sample (ACE_round (*latency));
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "low priority jitter (%u samples):\n", number_of_samples));
+ ACE_DEBUG ((LM_DEBUG,"Latency stats (time in usec)\n"));
+ stats.print_summary (1, 1, stderr);
+
+ // Return the square root of the sum of the differences computed
+ // above, i.e. jitter.
+ return sqrt (jitter / (number_of_samples - 1));
+}
+
+ACE_timer_t
+Client::get_jitter (u_int id)
+{
+ ACE_timer_t jitter = 0.0;
+ ACE_timer_t average = get_latency (id);
+ u_int number_of_samples = 0;
+
+ // Compute the standard deviation, i.e., jitter, from the values
+ // stored in the global_jitter_array_.
+
+ ACE_Stats stats;
+
+ // We first compute the sum of the squares of the differences each
+ // latency has from the average.
+
+ JITTER_ARRAY_ITERATOR iterator =
+ this->ts_->global_jitter_array_ [id]->begin ();
+
+ ACE_timer_t number_of_calls =
+ this->ts_->count_[id] / this->ts_->granularity_;
+
+ ACE_timer_t *latency = 0;
+
+ u_int i = 0;
+
+ for (iterator.first ();
+ i < number_of_calls && iterator.next (latency) == 1;
+ i ++,iterator.advance ())
+ {
+ ++number_of_samples;
+ ACE_timer_t difference = *latency - average;
+ jitter += difference * difference;
+ stats.sample (ACE_round (*latency));
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "jitter for thread id %u:\n", id));
+ ACE_DEBUG ((LM_DEBUG,"Latency stats (time in usec)\n"));
+ stats.print_summary (1, 1, stderr);
+
+ // Return the square root of the sum of the differences computed
+ // above, i.e. jitter.
+ return sqrt (jitter / (number_of_samples - 1));
+}
+
+void
+Client::find_frequency (void)
+{
+ if (this->ts_->thread_per_rate_ == 0)
+ {
+ if (this->id_ == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) I'm the high priority client, my id is %d.\n",
+ this->id_));
+ this->frequency_ = CB_HIGH_PRIORITY_RATE;
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) I'm a low priority client, my id is %d.\n",
+ this->id_));
+ this->frequency_ = CB_LOW_PRIORITY_RATE;
+ }
+ }
+ else
+ switch (this->id_)
+ {
+ case CB_20HZ_CONSUMER:
+ this->frequency_ = CB_20HZ_CONSUMER_RATE;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) I'm a %u Hz frequency client, "
+ "my id is %u.\n",
+ CB_20HZ_CONSUMER_RATE,
+ this->id_));
+ break;
+ case CB_10HZ_CONSUMER:
+ this->frequency_ = CB_10HZ_CONSUMER_RATE;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) I'm a %u Hz frequency client, "
+ "my id is %u.\n",
+ CB_10HZ_CONSUMER_RATE,
+ this->id_));
+ break;
+ case CB_5HZ_CONSUMER:
+ this->frequency_ = CB_5HZ_CONSUMER_RATE;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) I'm a %u Hz frequency client, "
+ "my id is %u.\n",
+ CB_5HZ_CONSUMER_RATE,
+ this->id_));
+ break;
+ case CB_1HZ_CONSUMER:
+ this->frequency_ = CB_1HZ_CONSUMER_RATE;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) I'm a %u Hz frequency client, "
+ "my id is %u.\n",
+ CB_1HZ_CONSUMER_RATE,
+ this->id_));
+ break;
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Invalid Thread ID!!!!\n",
+ this->id_));
+ }
+}
+
+CORBA::ORB_ptr
+Client::init_orb (ACE_ENV_SINGLE_ARG_DECL)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "I'm thread %t\n"));
+
+
+ // Convert the argv vector into a string.
+ ACE_ARGV tmp_args (this->argv_);
+ char tmp_buf[BUFSIZ];
+
+ ACE_OS::strcpy (tmp_buf,
+ tmp_args.buf ());
+ // Add the argument.
+ ACE_OS::strcat (tmp_buf,
+ " -ORBRcvSock 32768 "
+ " -ORBSndSock 32768 ");
+
+ ACE_DEBUG ((LM_DEBUG,
+ tmp_buf));
+
+ // Convert back to argv vector style.
+ ACE_ARGV tmp_args2 (tmp_buf);
+ int argc = tmp_args2.argc ();
+ char **argv = tmp_args2.argv ();
+
+ char orbid[64];
+ ACE_OS::sprintf (orbid, "orb:%d", this->id_);
+ CORBA::ORB_var orb = CORBA::ORB_init (argc,
+ argv,
+ orbid
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (CORBA::ORB::_nil ());
+
+ if (this->id_ == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "parsing the arguments\n"));
+
+ int result = this->ts_->parse_args (argc,
+ argv);
+ if (result != 0)
+ return CORBA::ORB::_nil ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t)Arguments parsed successfully\n"));
+
+ ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ready_mon,
+ this->ts_->ready_mtx_,
+ CORBA::ORB::_nil ());
+ this->ts_->ready_ = 1;
+ this->ts_->ready_cnd_.broadcast ();
+ ready_mon.release ();
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) ORB_init success\n"));
+ return orb._retn ();
+}
+
+int
+Client::get_cubit (CORBA::ORB_ptr orb ACE_ENV_ARG_DECL)
+{
+ char *my_ior =
+ this->ts_->use_utilization_test_ == 1
+ ? this->ts_->one_ior_
+ : this->ts_->iors_[this->id_];
+
+ // If we are running the "1 to n" test make sure all low
+ // priority clients use only 1 low priority servant.
+ if (this->id_ > 0
+ && this->ts_->one_to_n_test_ == 1)
+ my_ior = this->ts_->iors_[1];
+
+ if (my_ior == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Must specify valid ior filename with -f option\n"),
+ -1);
+
+ CORBA::Object_var objref =
+ orb->string_to_object (my_ior
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (-1);
+
+ if (CORBA::is_nil (objref.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%t) string_to_object Failed!\n"),
+ -1);
+
+ // Narrow the CORBA::Object reference to the stub object,
+ // checking the type along the way using _is_a.
+ this->cubit_ = Cubit::_narrow (objref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (-1);
+
+ if (CORBA::is_nil (this->cubit_))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Create cubit failed\n"),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Binding succeeded\n"));
+
+ CORBA::String_var str =
+ orb->object_to_string (this->cubit_
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (-1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) CUBIT OBJECT connected to <%s>\n",
+ str.in ()));
+
+ return 0;
+}
+
+int
+Client::svc (void)
+{
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ // Initialize the ORB.
+ CORBA::ORB_var orb = this->init_orb (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Find the frequency of CORBA requests based on thread id.
+ this->find_frequency ();
+
+ // Get the cubit object from the file.
+ int r = this->get_cubit (orb.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ if (r != 0)
+ return r;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Waiting for other threads to "
+ "finish binding..\n"));
+
+ // Wait for all the client threads to be initialized before going
+ // any further.
+ this->ts_->barrier_->wait ();
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t; %D) Everyone's done, here I go!!\n"));
+ if (this->ts_->oneway_ == 1)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) **** USING ONEWAY CALLS ****\n"));
+
+ // Perform the tests.
+ int result = this->run_tests ();
+ if (result != 0)
+ return result;
+
+ // release the semaphore
+ if (this->ts_->thread_per_rate_ == 1
+ && this->id_ == this->ts_->thread_count_ - 1)
+ this->ts_->semaphore_->release (this->ts_->thread_count_ - 1);
+ else
+ this->ts_->semaphore_->release ();
+
+ // shutdown the server if necessary.
+ if (this->ts_->shutdown_)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) CALLING SHUTDOWN() ON THE SERVANT\n"));
+ this->cubit_->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+
+ CORBA::release (this->cubit_);
+ this->cubit_ = 0;
+
+ orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Task_Client::svc()");
+ }
+ ACE_ENDTRY;
+
+ // To avoid a memPartFree on VxWorks. It will leak memory, though.
+ ACE_THR_FUNC_RETURN status = 0;
+
+ if (thr_mgr ())
+ thr_mgr ()->exit (status, 1);
+ else
+ ACE_OS::thr_exit (status);
+
+ return 0;
+}
+
+int
+Client::cube_octet (void)
+{
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ this->call_count_++;
+ // Cube an octet.
+ CORBA::Octet arg_octet = func (this->num_);
+ CORBA::Octet ret_octet = 0;
+
+ START_QUANTIFY;
+
+ if (this->ts_->use_utilization_test_ == 1 && this->ts_->remote_invocations_ == 0)
+ ret_octet = this->cubit_impl_.cube_octet (arg_octet
+ ACE_ENV_ARG_PARAMETER);
+ else
+ ret_octet = this->cubit_->cube_octet (arg_octet
+ ACE_ENV_ARG_PARAMETER);
+
+ STOP_QUANTIFY;
+ ACE_TRY_CHECK;
+
+ // Perform the cube operation.
+ arg_octet = arg_octet * arg_octet * arg_octet;
+
+ if (arg_octet != ret_octet)
+ {
+ this->error_count_++;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "** cube_octet (%d) (--> %d)\n",
+ arg_octet,
+ ret_octet),
+ -1);
+ }
+
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "call to cube_octet()\n");
+ return -1;
+ }
+ ACE_ENDTRY;
+ return 0;
+}
+
+int
+Client::cube_short (void)
+{
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ this->call_count_++;
+
+ CORBA::Short arg_short = func (this->num_);
+ CORBA::Short ret_short;
+
+ START_QUANTIFY;
+ ret_short = this->cubit_->cube_short (arg_short
+ ACE_ENV_ARG_PARAMETER);
+ STOP_QUANTIFY;
+ ACE_TRY_CHECK;
+ arg_short = arg_short * arg_short * arg_short;
+
+ if (arg_short != ret_short)
+ {
+ this->error_count_++;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "** cube_short (%d) (--> %d)\n",
+ arg_short ,
+ ret_short),
+ -1);
+ }
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "call to cube_short\n");
+ return -1;
+ }
+ ACE_ENDTRY;
+ return 0;
+}
+
+int
+Client::cube_long (void)
+{
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ this->call_count_++;
+
+ CORBA::Long arg_long = func (this->num_);
+ CORBA::Long ret_long;
+
+ START_QUANTIFY;
+ ret_long = this->cubit_->cube_long (arg_long
+ ACE_ENV_ARG_PARAMETER);
+ STOP_QUANTIFY;
+ ACE_TRY_CHECK;
+
+ arg_long = arg_long * arg_long * arg_long;
+
+ if (arg_long != ret_long)
+ {
+ this->error_count_++;
+ ACE_ERROR ((LM_ERROR,
+ "** cube_long (%d) (--> %d)\n",
+ arg_long,
+ ret_long));
+ }
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "call to cube_long()\n");
+ return -1;
+ }
+ ACE_ENDTRY;
+ return 0;
+}
+
+int
+Client::cube_struct (void)
+{
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ Cubit::Many arg_struct;
+ Cubit::Many ret_struct;
+
+ this->call_count_++;
+
+ arg_struct.l = func (this->num_);
+ arg_struct.s = func (this->num_);
+ arg_struct.o = func (this->num_);
+
+ START_QUANTIFY;
+ ret_struct = this->cubit_->cube_struct (arg_struct
+ ACE_ENV_ARG_PARAMETER);
+ STOP_QUANTIFY;
+ ACE_TRY_CHECK;
+
+ arg_struct.l = arg_struct.l * arg_struct.l * arg_struct.l ;
+ arg_struct.s = arg_struct.s * arg_struct.s * arg_struct.s ;
+ arg_struct.o = arg_struct.o * arg_struct.o * arg_struct.o ;
+
+ if (arg_struct.l != ret_struct.l
+ || arg_struct.s != ret_struct.s
+ || arg_struct.o != ret_struct.o )
+ {
+ this->error_count_++;
+ ACE_ERROR ((LM_ERROR,
+ "**cube_struct error!\n"));
+ }
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "call to cube_struct()\n");
+ return -1;
+ }
+ ACE_ENDTRY;
+ return 0;
+}
+
+int
+Client::make_request (void)
+{
+ int result;
+
+ if (this->ts_->oneway_ == 0)
+ {
+ switch (this->ts_->datatype_)
+ {
+ case CB_OCTET:
+ result = this->cube_octet ();
+ break;
+ // Cube a short.
+ case CB_SHORT:
+ result = this->cube_short ();
+ break;
+ // Cube a long.
+ case CB_LONG:
+ result = this->cube_long ();
+ break;
+ // Cube a "struct" ...
+ case CB_STRUCT:
+ result = this->cube_struct ();
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t); %s:%d; unexpected datatype: %d\n",
+ this->ts_->datatype_), -1);
+ }
+ if (result != 0)
+ return result;
+ }
+ else
+ {
+ ACE_DECLARE_NEW_CORBA_ENV;
+ ACE_TRY
+ {
+ this->call_count_++;
+ START_QUANTIFY;
+ this->cubit_->noop (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ STOP_QUANTIFY;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "oneway call noop()\n");
+ return -1;
+ }
+ ACE_ENDTRY;
+ }
+ // return success.
+ return 0;
+}
+
+void
+Client::print_stats (void)
+{
+ // Perform latency stats only if we are not running the utilization
+ // tests.
+ if (this->call_count_ > 0
+ && this->ts_->use_utilization_test_ == 0)
+ {
+ if (this->error_count_ == 0)
+ {
+ // Latency is in usecs.
+ ACE_timer_t calls_per_second =
+ (this->call_count_ * ACE_ONE_SECOND_IN_USECS) / this->latency_;
+
+ // Calculate average (per-call) latency in usecs.
+ this->latency_ = this->latency_/this->call_count_;
+
+ if (this->latency_ > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) cube average call ACE_OS::time\t= %A msec, \t"
+ "%A calls/second\n",
+ this->latency_ / ACE_ONE_SECOND_IN_MSECS,
+ calls_per_second));
+ this->put_latency (this->my_jitter_array_,
+ this->latency_,
+ this->id_,
+ this->call_count_);
+ }
+ else
+ {
+ // Still we have to call this function to store a valid
+ // array pointer.
+ this->put_latency (this->my_jitter_array_,
+ 0,
+ this->id_,
+ this->call_count_);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "*** Warning: Latency, %f, is less than or equal to zero."
+ " Precision may have been lost.\n, this->latency_"));
+ }
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ "%d calls, %d errors\n",
+ this->call_count_,
+ this->error_count_));
+ }
+}
+
+ACE_timer_t
+Client::calc_delta (ACE_timer_t real_time,
+ ACE_timer_t delta)
+{
+ ACE_timer_t new_delta;
+#if defined (ACE_LACKS_FLOATING_POINT)
+ new_delta = 40 * real_time / 100 + 60 * delta / 100;
+#else /* !ACE_LACKS_FLOATING_POINT */
+ new_delta = 0.4 * fabs (real_time) + 0.6 * delta;
+#endif /* ACE_LACKS_FLOATING_POINT */
+ return new_delta;
+}
+
+int
+Client::do_test (void)
+{
+ ACE_timer_t delta = 0;
+ u_int low_priority_client_count = this->ts_->thread_count_ - 1;
+ ACE_timer_t sleep_time = // usec
+ (ACE_ONE_SECOND_IN_USECS * this->ts_->granularity_)/this->frequency_;
+ u_int i;
+ int result = 0;
+
+ for (i = 0;
+ // keep running for loop count, OR
+ i < this->ts_->loop_count_
+ // keep running if we are the highest priority thread and at
+ // least another lower client thread is running, OR
+ || (id_ == 0 && this->ts_->thread_count_ > 1)
+ // keep running if test is thread_per_rate and we're not the
+ // lowest frequency thread.
+ || (this->ts_->thread_per_rate_ == 1
+ && id_ < (this->ts_->thread_count_ - 1));
+ i++)
+ {
+ // Start timing a call.
+ if ((i % this->ts_->granularity_) == 0 &&
+ this->ts_->use_utilization_test_ == 0)
+ {
+ // Delay a sufficient amount of time to be able to enforce
+ // the calling frequency, e.g., 20Hz, 10Hz, 5Hz, 1Hz.
+ ACE_Time_Value tv (0,
+ (u_long) (sleep_time < delta
+ ? 0
+ : sleep_time - delta));
+ ACE_OS::sleep (tv);
+ this->timer_->start ();
+ }
+ this->num_ = i;
+ // make a request to the server object depending on the datatype.
+ result = this->make_request ();
+ if (result != 0)
+ return 2;
+
+ // Stop the timer.
+ if (i % this->ts_->granularity_ == this->ts_->granularity_ - 1
+ && this->ts_->use_utilization_test_ == 0)
+ {
+ this->timer_->stop ();
+
+ // Calculate time elapsed.
+ ACE_timer_t real_time;
+ real_time = this->timer_->get_elapsed ();
+ // Recalculate delta = 0.4 * elapsed_time + 0.6 *
+ // delta. This is used to adjust the sleeping time so that
+ // we make calls at the required frequency.
+ delta = this->calc_delta (real_time,delta);
+ this->latency_ += real_time * this->ts_->granularity_;
+
+ if ((result = this->my_jitter_array_->enqueue_tail (real_time)) != 0)
+ ACE_DEBUG ((LM_DEBUG, "(%t) Error: my_jitter_array->enqueue_tail() returned %d\n", result));
+ }
+ if (this->ts_->thread_per_rate_ == 1
+ && id_ < (this->ts_->thread_count_ - 1))
+ {
+ if (this->ts_->semaphore_->tryacquire () != -1)
+ break;
+ }
+ else
+ // If we are the high priority client. If tryacquire()
+ // succeeded then a client must have done a release () on it,
+ // thus we decrement the client counter.
+ if (id_ == 0
+ && this->ts_->thread_count_ > 1)
+ {
+ if (this->ts_->semaphore_->tryacquire () != -1)
+ {
+ low_priority_client_count --;
+ // If all clients are done then break out of loop.
+ if (low_priority_client_count <= 0)
+ break;
+ }
+ }
+
+ } /* end of for () */
+ ACE_DEBUG ((LM_DEBUG, "(%t; %D) do_test executed %u iterations\n", i));
+
+ return 0;
+}
+
+int
+Client::run_tests (void)
+{
+ int result;
+ ACE_NEW_RETURN (this->my_jitter_array_,
+ JITTER_ARRAY,
+ -1);
+
+ ACE_NEW_RETURN (this->timer_,
+ MT_Cubit_Timer (this->ts_->granularity_),
+ -1);
+ if (this->ts_->use_utilization_test_ == 1)
+ this->timer_->start ();
+
+ // Make the calls in a loop.
+ result = this->do_test ();
+ if (result != 0)
+ return result;
+
+ if (id_ == 0)
+ this->ts_->high_priority_loop_count_ =
+ this->call_count_;
+
+ if (this->ts_->use_utilization_test_ == 1)
+ {
+ this->timer_->stop ();
+ this->ts_->util_test_time_ = this->timer_->get_elapsed ();
+ }
+
+ // Print the latency results.
+ this->print_stats ();
+ return 0;
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h
new file mode 100644
index 00000000000..98b43509b90
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Task_Client.h
@@ -0,0 +1,372 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// Task_Client.h
+//
+// = AUTHOR
+// Andy Gokhale, Sumedh Mungee, Sergio Flores-Gaitan, and
+// Nagarajan Surendran.
+//
+// ============================================================================
+
+#ifndef TASK_CLIENT_H
+#define TASK_CLIENT_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Task.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Get_Opt.h"
+#include "ace/Profile_Timer.h"
+#include "ace/ARGV.h"
+#include "ace/Sched_Params.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Containers.h"
+
+#include "cubitC.h"
+#include "cubit_i.h"
+#include "Globals.h"
+#include "Timer.h"
+
+#if defined (CHORUS_MVME)
+# include "pccTimer.h"
+#endif /* CHORUS_MVME */
+
+// FUZZ: disable check_for_math_include
+#if defined(ACE_HAS_EXCEPTIONS) && !defined (__KCC) && !defined (__xlC__) && \
+ (!defined __GNUG__ || !defined (DIGITAL_UNIX))
+ // Some plaforms define an exception structure in math.h...
+# if defined (__GNUG__)
+ // And some compilers have this workaround. Disable it with this
+ // #define, to avoid warning about multiple #defines of exception.
+# define _MATH_H_WRAPPER
+# endif /* __GNUG__ */
+# define exception _math_exception
+# include /**/ <math.h>
+# undef exception
+#else
+# include /**/ <math.h>
+#endif /* ACE_HAS_EXCEPTIONS */
+
+#if defined (ACE_LACKS_FLOATING_POINT)
+// The following is just temporary, until we finish the sqrt()
+// implementation.
+#define sqrt(X) (1)
+#endif /* ACE_LACKS_FLOATING_POINT */
+
+#if defined (ACE_HAS_QUANTIFY)
+# define START_QUANTIFY quantify_start_recording_data ();
+# define STOP_QUANTIFY quantify_stop_recording_data();
+# define CLEAR_QUANTIFY quantify_clear_data ();
+#else /* ! ACE_HAS_QUANTIFY */
+# define START_QUANTIFY
+# define STOP_QUANTIFY
+# define CLEAR_QUANTIFY
+#endif /* ! ACE_HAS_QUANTIFY */
+
+
+enum Cubit_Datatypes
+{
+ // = The various datatypes the client and the server can exchange.
+ CB_OCTET,
+ CB_SHORT,
+ CB_LONG,
+ CB_STRUCT,
+
+ // = Rate constants.
+ CB_20HZ_CONSUMER = 0,
+ CB_10HZ_CONSUMER = 1,
+ CB_5HZ_CONSUMER = 2,
+ CB_1HZ_CONSUMER = 3,
+
+ CB_20HZ_CONSUMER_RATE = 20,
+ CB_10HZ_CONSUMER_RATE = 10,
+ CB_5HZ_CONSUMER_RATE = 5,
+ CB_1HZ_CONSUMER_RATE = 1,
+
+ CB_HIGH_PRIORITY_RATE = 20,
+ CB_LOW_PRIORITY_RATE = 10
+};
+
+typedef ACE_Unbounded_Queue<ACE_timer_t> JITTER_ARRAY;
+typedef ACE_Unbounded_Queue_Iterator<ACE_timer_t> JITTER_ARRAY_ITERATOR;
+
+class Task_State
+{
+ // = TITLE
+ // Maintains state common to multiple Cubit clients.
+ //
+ // = DESCRIPTION
+ // This class maintains state which is common to the potentially
+ // multiple concurrent clients.
+public:
+ Task_State (void);
+ // Constructor.
+
+ int parse_args (int argc,char **argv);
+ // parses the arguments with the provided argc and argv.
+
+ ~Task_State (void);
+ // Destructor
+
+ ACE_Barrier *barrier_;
+ // Barrier for the multiple clients to synchronize after binding to
+ // the servants.
+
+ const char *key_;
+ // All cubit objects will have this as prefix to its key.
+
+ u_int loop_count_;
+ // Number of times to loop, making calls.
+
+ u_int thread_count_;
+ // Number of concurrent clients to create.
+
+ ACE_timer_t *latency_;
+ // Array to store the latency for every client, indexed by
+ // thread-id.
+
+ int *ave_latency_;
+ // Int array to store the latencies.
+
+ Cubit_Datatypes datatype_;
+ // Which datatype to use to make the calls.
+
+ TAO_SYNCH_MUTEX lock_;
+ // Lock to protect access to this object.
+
+ u_int thread_per_rate_;
+ // Flag for the thread_per_rate test.
+
+ JITTER_ARRAY **global_jitter_array_;
+ // This array stores the latency seen by each client for each
+ // request, to be used later to compute jitter.
+
+ u_int *count_;
+ // This array stores the call count of each thread. They will not
+ // always have the same call count.
+
+ u_int shutdown_;
+ // Flag that indicates if we are going to call the shutdown methos
+ // for the servant.
+
+ u_int oneway_;
+ // Flag that indicates if we are going to use oneway calls instead
+ // of two-way.
+
+ char *one_ior_;
+ // Ior array used if utilization test is run.
+
+ u_int one_to_n_test_;
+ // indicates whether we are running the "1 to n" test, which has 1
+ // low priority servant and n low priority clients.
+
+ u_int context_switch_test_;
+ // flag to run context switch test
+
+ char **iors_;
+ // Array of pointers used to hold the ior strings read from the ior file
+ // that the server created.
+
+ int iors_count_;
+ // count on the number of iors
+
+ char *ior_file_;
+ // Name of the filename that the server used to store the iors.
+
+ u_int granularity_;
+ // this is the granularity of the timing of the CORBA requests. A
+ // value of 5 represents that we will take time every 5 requests,
+ // instead of the default of every request (1).
+
+ u_int use_utilization_test_;
+ // flag to indicate we are to use the utilization test. By default
+ // we do not use it, because it can cause starvation with real-time
+ // threads
+
+ u_int high_priority_loop_count_;
+ // Number of times the high priority looped. We are going to loop
+ // as long as there is low priority clients running, so as to
+ // maintain high priority traffic as long as low priority traffic is
+ // going through.
+
+ ACE_SYNCH_SEMAPHORE *semaphore_;
+ // semaphore in order for the high priority client to keep running
+ // as long as the low priority clients are running. See explanation
+ // of "high_priority_loop_count_" member in this class.
+
+ u_int use_multiple_priority_;
+ // flag to indicate we are to use multiple priorities for the low
+ // priority clients. By default we use only one priority for all
+ // client threads.
+
+ ACE_High_Res_Timer timer_;
+ // global timer to be started by the utilization task.
+
+ int ready_;
+ // ready flag used by the high priority thread to wake up the low
+ // priority threads after it's parsed the arguments.
+
+ TAO_SYNCH_MUTEX ready_mtx_;
+ // mutex for the condition variable.
+
+ TAO_SYNCH_CONDITION ready_cnd_;
+ // condition variable for the low priority threads to wait
+ //until the high priority thread is done with the arguments parsing.
+
+ u_int remote_invocations_;
+ // flag to indicate whether we make remote versus local invocations
+ // to calculate accurately the ORB overhead.
+
+ ACE_timer_t util_test_time_;
+ // holds the total time for the utilization test to complete.
+};
+
+class Client : public ACE_Task<ACE_SYNCH>
+{
+ // = TITLE
+ // The Cubit client.
+ //
+ // = DESCRIPTION
+ // This class implements the Cubit Client, which is an active object.
+ // `n' threads execute svc, and make 2way CORBA calls on the server
+public:
+ Client (ACE_Thread_Manager *,
+ Task_State *ts,
+ int argc,
+ char **argv,
+ u_int id);
+ // Constructor, with a pointer to the common task state.
+
+ ~Client (void);
+ // destructor.
+
+ virtual int svc (void);
+ // The thread function.
+
+ ACE_timer_t get_high_priority_latency (void);
+ // Returns the latency of the high priority thread in usecs.
+
+ ACE_timer_t get_low_priority_latency (void);
+ // Returns the average latency found for the low
+ // priority threads in usecs.
+
+ ACE_timer_t get_high_priority_jitter (void);
+ // Returns the high priority jitter in usecs.
+
+ ACE_timer_t get_low_priority_jitter (void);
+ // Returns the jitter for all the low priority
+ // thread request in usecs.
+
+ ACE_timer_t get_latency (u_int thread_id);
+ // gets the average latency for that thread.
+
+ ACE_timer_t get_jitter (u_int id);
+ // gets the jitter for this thread.
+
+ static int func (u_int i);
+ // Arbitrary generator used by the client to create the numbers to be
+ // cubed.
+
+private:
+ CORBA::ORB_ptr init_orb (ACE_ENV_SINGLE_ARG_DECL);
+ // initialize the ORB.
+
+ void read_ior (void);
+ // reads the cubit ior from a file.
+
+ int get_cubit (CORBA::ORB_ptr orb
+ ACE_ENV_ARG_DECL);
+ // gets the cubit object.
+
+ int run_tests (void);
+ // Run the various tests.
+
+ int make_request (void);
+ // make a CORBA request depending on the datatype.
+
+ int do_test (void);
+ // makes the corba requests.
+
+ int cube_octet (void);
+ // call cube_octet method on the cubit object.
+
+ int cube_short (void);
+ // call cube short on the cubit object.
+
+ int cube_long (void);
+ // call cube long on the cubit object.
+
+ int cube_struct (void);
+ // call cube struct on the cubit object.
+
+ void print_stats (void);
+ // prints the latency stats.
+
+ void put_latency (JITTER_ARRAY *jitter,
+ ACE_timer_t latency,
+ u_int thread_id,
+ u_int count);
+ // Records the latencies in the <Task_State>.
+
+ int parse_args (int, char **);
+ // Parses the arguments.
+
+ void find_frequency (void);
+ // determines the frequency at which to make calls depending on the
+ // id of the thread.
+
+ ACE_timer_t calc_delta (ACE_timer_t real_time,
+ ACE_timer_t delta);
+ // calculate the delta value.
+
+ Cubit_ptr cubit_;
+ // pointer to the cubit object.
+
+ Cubit_i cubit_impl_;
+ // cubit implementation object.
+
+ Task_State *ts_;
+ // Pointer to shared state.
+
+ u_int num_;
+ // number used for cubing.
+
+ u_int id_;
+ // unique id of the task
+
+ u_int call_count_;
+ // count of the number of calls made.
+
+ u_int error_count_;
+ // number of calls that failed.
+
+ JITTER_ARRAY *my_jitter_array_;
+ // ACE Unbounded set holding the latency values for all the
+ // requests of this thread.
+
+ MT_Cubit_Timer *timer_;
+ // Timer using pccTimer for chorus and ACE_Timer for other platforms.
+
+ ACE_timer_t frequency_;
+ // frequency of CORBA requests.
+
+ ACE_timer_t latency_;
+ // aggregate latency of the requests.
+
+ // command-line arguments.
+ int argc_;
+ char **argv_;
+};
+
+#endif /* !defined (TASK_CLIENT_H) */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Timer.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Timer.cpp
new file mode 100644
index 00000000000..23cc89ffc17
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Timer.cpp
@@ -0,0 +1,56 @@
+/* $Id$ */
+
+#include "Timer.h"
+#include "Task_Client.h"
+
+MT_Cubit_Timer::MT_Cubit_Timer (u_int granularity)
+ :granularity_ (granularity)
+#if defined (CHORUS_MVME)
+ , pstartTime_ (0)
+ , pstopTime_ (0)
+#endif /* CHORUS_MVME */
+{
+}
+
+void
+MT_Cubit_Timer::start (void)
+{
+#if defined (CHORUS_MVME)
+ this->pstartTime_ = pccTime1Get();
+#else /* CHORUS_MVME */
+ this->timer_.start ();
+#endif /* !CHORUS_MVME */
+}
+
+void
+MT_Cubit_Timer::stop (void)
+{
+#if defined (CHORUS_MVME)
+ this->pstopTime_ = pccTime1Get ();
+#else /* CHORUS_MVME */
+ // If CHORUS_MVME is not defined just use plain timer_.stop ().
+ this->timer_.stop ();
+ this->timer_.elapsed_time (this->delta_);
+#endif /* !CHORUS_MVME */
+}
+
+ACE_timer_t
+MT_Cubit_Timer::get_elapsed (void)
+{
+ ACE_timer_t real_time;
+#if defined (ACE_LACKS_FLOATING_POINT)
+# if defined (CHORUS_MVME)
+ real_time = (this->pstopTime_ - this->pstartTime_) / this->granularity_;
+# else /* CHORUS_MVME */
+ // Store the time in usecs.
+ real_time = (this->delta_.sec () * ACE_ONE_SECOND_IN_USECS +
+ this->delta_.usec ()) / this->granularity_;
+# endif /* !CHORUS_MVME */
+#else /* !ACE_LACKS_FLOATING_POINT */
+ // Store the time in usecs.
+ real_time = (ACE_timer_t) this->delta_.sec () * ACE_ONE_SECOND_IN_USECS +
+ (ACE_timer_t) this->delta_.usec ();
+ real_time = real_time/this->granularity_;
+#endif /* !ACE_LACKS_FLOATING_POINT */
+ return real_time; // in usecs.
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Timer.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Timer.h
new file mode 100644
index 00000000000..45c22dbb567
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Timer.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+/* $Id$ */
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// Timer.h
+//
+// = AUTHOR
+// Andy Gokhale, Sumedh Mungee, Sergio Flores-Gaitan and Nagarajan
+// Surendran.
+//
+// ============================================================================
+
+#ifndef _MT_CUBIT_TIMER_H
+#define _MT_CUBIT_TIMER_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/High_Res_Timer.h"
+
+class MT_Cubit_Timer
+{
+ // = TITLE
+ // A class that encapsulates the pccTimer for chorus and uses
+ // ACE Timer for other platforms.
+public:
+ MT_Cubit_Timer (u_int granularity);
+
+ void start (void);
+ void stop (void);
+
+ ACE_timer_t get_elapsed (void);
+
+private:
+ ACE_High_Res_Timer timer_;
+ // timer.
+
+ ACE_Time_Value delta_;
+ // Elapsed time in microseconds.
+
+ u_int granularity_;
+ // This is the granularity of the timing of the CORBA requests. A
+ // value of 5 represents that we will take time every 5 requests,
+ // instead of the default of every request (1).
+
+#if defined (CHORUS_MVME)
+ // Variables for the pccTimer.
+ int pstartTime_;
+ int pstopTime_;
+#endif /* CHORUS_MVME */
+};
+
+#endif /* _MT_CUBIT_TIMER_H */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Util_Thread.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Util_Thread.cpp
new file mode 100644
index 00000000000..98564ca9266
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Util_Thread.cpp
@@ -0,0 +1,99 @@
+// $Id$
+
+#include "Util_Thread.h"
+#include "ace/ACE.h"
+#include "ace/Barrier.h"
+
+ACE_RCSID(MT_Cubit, Util_Thread, "$Id$")
+
+Util_Thread::Util_Thread (Task_State *ts,
+ ACE_Thread_Manager *thr_mgr)
+ : ACE_Task<ACE_NULL_SYNCH> (thr_mgr),
+ done_ (0),
+ number_of_computations_ (0),
+ ts_ (ts)
+{
+}
+
+int
+Util_Thread::svc (void)
+{
+ ACE_hthread_t thr_handle;
+ ACE_Thread::self (thr_handle);
+ int prio;
+
+ if (ACE_OS::thr_getprio (thr_handle, prio) == -1)
+ return -1;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Utilization Thread created with priority %d, "
+ "waiting for threads to finish binding\n",
+ prio));
+
+ // This barrier synchronizes the utilization thread with the client
+ // threads i.e., the Util_thread should wait until all the clients
+ // have finished binding, and only then start measuring the
+ // utilization.
+ this->ts_->barrier_->wait ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) )))))))) "
+ "utilization test STARTED at %D\n"));
+
+ this->ts_->timer_.start ();
+ this->run_computations ();
+ this->ts_->timer_.stop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) (((((((( "
+ "utilization test ENDED at %D\n"));
+ return 0;
+}
+
+u_long
+Util_Thread::get_number_of_computations (void)
+{
+ return this->number_of_computations_;
+}
+
+// Computation performed by the Utilization thread. We need this in a
+// separate function to get it's execution time.
+
+void
+Util_Thread::computation (void)
+{
+ // This is the number that the Util_Thread uses to check for
+ // primality.
+ const u_long CUBIT_PRIME_NUMBER = 509UL;
+
+ // See if this number is prime. 2 and CUBIT_PRIME_NUMBER / 2 are
+ // the recommended values for min_factor and max_factor, as
+ // explained in ACE.h (is_prime).
+ ACE::is_prime (CUBIT_PRIME_NUMBER,
+ 2UL,
+ CUBIT_PRIME_NUMBER / 2);
+}
+
+// Perform repeated prime factor computations on an arbitrary number.
+// And you thought your life was boring... :-)
+
+int
+Util_Thread::run_computations (void)
+{
+ while (this->done_ == 0)
+ {
+ // Bound the number of computations, since we can potentially
+ // block the machine if this thread never leaves the loop.
+ if (this->number_of_computations_ > (ts_->loop_count_ * UTIL_BOUND_CONSTANT))
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "\t(%t) utilization test breaking loop so machine won't block.\n"));
+ break;
+ }
+
+ this->computation ();
+ this->number_of_computations_++;
+ }
+
+ return 0;
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/Util_Thread.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Util_Thread.h
new file mode 100644
index 00000000000..cad2577da57
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/Util_Thread.h
@@ -0,0 +1,57 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// Util_Thread.h
+//
+// = AUTHOR
+// Andy Gokhale, Sumedh Mungee, Sergio Flores-Gaitan and Nagarajan
+// Surendran.
+//
+// ============================================================================
+
+#ifndef UTIL_THREAD_H
+#define UTIL_THREAD_H
+
+#include "Task_Client.h"
+
+class Util_Thread : public ACE_Task<ACE_NULL_SYNCH>
+{
+ // = TITLE
+ // The thread that computes utilization.
+public:
+ Util_Thread (Task_State *,
+ ACE_Thread_Manager *thr_mgr);
+ // Constructor.
+
+ virtual int svc (void);
+ // The thread entry point function.
+
+ u_long get_number_of_computations (void);
+ // Gets the number of computations the thread was able to perform.
+
+ void computation (void);
+ // this is the actual "computation" being performed.
+
+ int done_;
+ // Indicates whether we're done.
+
+private:
+ int run_computations (void);
+ // Run the computations.
+
+ u_long number_of_computations_;
+ // This stores the number of computations performed
+ // by the Util_Thread so far
+
+ Task_State *ts_;
+ // Pointer to the Task state. Stores the state
+ // common to the multiple client threads
+};
+
+#endif /* !defined (UTIL_THREAD_H) */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp
new file mode 100644
index 00000000000..e0d97da8166
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.cpp
@@ -0,0 +1,865 @@
+// $Id$
+
+#include "ace/config-all.h"
+
+#if defined (ACE_VXWORKS) && !defined (__RTP__)
+# undef ACE_MAIN
+# define ACE_MAIN client
+#endif /* ACE_VXWORKS && !__RTP__ */
+
+#include "ace/Sched_Params.h"
+#include "tao/Strategies/advanced_resource.h"
+#include "server.h"
+#include "client.h"
+#include "Globals.h"
+#include "ace/Barrier.h"
+
+#if defined (ACE_HAS_QUANTIFY)
+# include "quantify.h"
+#endif /* ACE_HAS_QUANTIFY */
+
+ACE_RCSID(MT_Cubit, client, "$Id$")
+
+#if defined (ACE_VXWORKS) && !defined (__RTP__) && !defined (ACE_HAS_PTHREADS)
+u_int ctx = 0;
+u_int ct = 0;
+
+typedef struct
+{
+ char name[15];
+ WIND_TCB *tcb;
+#if (CPU_FAMILY == PPC)
+ INSTR pc;
+#else
+ INSTR *pc;
+#endif
+} task_info;
+
+const u_int SWITCHES = 25000;
+task_info tInfo[SWITCHES];
+
+extern "C"
+int
+switchHook (WIND_TCB *pOldTcb, // pointer to old task's WIND_TCB.
+ WIND_TCB *pNewTcb) // pointer to new task's WIND_TCB.
+{
+ ACE_UNUSED_ARG (pOldTcb);
+
+ // We create the client threads with names starting with "@".
+ char* name = ::taskName (::taskIdSelf ());
+ if (name[0] == '@')
+ ++ctx;
+
+ if (ct < SWITCHES)
+ {
+ ACE_OS::strncpy (tInfo[ct].name,
+ name,
+ TASKNAME_LEN);
+ tInfo[ct].tcb = pNewTcb;
+ tInfo[ct].pc = pNewTcb->regs.pc;
+ ++ct;
+ }
+
+ return 0;
+}
+#endif /* ACE_VXWORKS && !__RTP__ && !ACE_HAS_PTHREADS */
+
+// Constructor.
+
+Client_i::Client_i (void)
+ : high_priority_client_ (0),
+ low_priority_client_ (0),
+ util_thread_ (0),
+ ts_ (0),
+ num_low_priority_ (0),
+ num_priorities_ (0),
+ grain_ (0),
+ counter_ (0),
+ task_id_ (0),
+ argc_ (0),
+ argv_ (0),
+ context_switch_ (0)
+{
+}
+
+// Destructor.
+
+Client_i::~Client_i (void)
+{
+ delete this->high_priority_client_;
+ if (this->low_priority_client_ != 0)
+ // Delete the low priority task array.
+ for (u_int i = this->num_low_priority_;
+ i > 0;
+ i--)
+ delete this->low_priority_client_[i - 1];
+ delete [] this->low_priority_client_;
+ delete this->util_thread_;
+ delete this->ts_;
+}
+
+int
+Client_i::init (int argc, char *argv[])
+{
+ this->argc_ = argc;
+ this->argv_ = argv;
+
+ int result;
+ result = GLOBALS::instance ()->sched_fifo_init ();
+ if (result == -1)
+ return result;
+ VX_VME_INIT;
+ FORCE_ARGV (this->argc_,this->argv_);
+ // Make sure we've got plenty of socket handles. This call will use
+ // the default maximum.
+ ACE::set_handle_limit ();
+
+ ACE_NEW_RETURN (this->ts_,
+ Task_State,
+ -1);
+
+ // Preliminary argument processing.
+ for (int i=0;
+ i< this->argc_;
+ ++i)
+ {
+ if (ACE_OS::strcmp (this->argv_[i],"-r") == 0)
+ this->ts_->thread_per_rate_ = 1;
+ else if (ACE_OS::strcmp (this->argv_[i],"-t") == 0
+ && (i - 1 < this->argc_))
+ this->ts_->thread_count_ =
+ ACE_OS::atoi (this->argv_[i+1]);
+ }
+ PCCTIMER_INIT;
+ return 0;
+}
+
+void
+Client_i::run (void)
+{
+ if (this->ts_->thread_per_rate_ == 0)
+ {
+ this->do_priority_inversion_test ();
+
+ if (this->ts_->use_utilization_test_ == 1)
+ {
+ // Exit. Otherwise, the process just waits forever.
+ ACE_OS::exit ();
+ }
+ }
+ else
+ this->do_thread_per_rate_test ();
+}
+
+#if defined (ACE_VXWORKS) && !defined (__RTP__) && !defined (ACE_HAS_PTHREADS)
+void
+Client_i::output_taskinfo (void)
+{
+ FILE *file_handle = ACE_OS::fopen ("taskinfo.txt", "w");
+
+ if (file_handle == 0)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "open"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "--->Output file for taskinfo data is \"taskinfo.txt\"\n"));
+
+ // This loop visits each client. thread_count_ is the number of
+ // clients.
+
+ for (u_int j = 0; j < SWITCHES; ++j)
+ ACE_OS::fprintf(file_handle,
+ "\tname= %s\ttcb= %p\tpc= %p\n",
+ tInfo[j].name,
+ tInfo[j].tcb,
+ tInfo[j].pc);
+
+ ACE_OS::fclose (file_handle);
+}
+#endif /* ACE_VXWORKS && !__RTP__ && !ACE_HAS_PTHREADS */
+
+void
+Client_i::get_context_switches (void)
+{
+#if (defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)) && !defined (ACE_WIN32)
+
+ if (this->ts_->context_switch_test_ == 1)
+ {
+ this->timer_for_context_switch.start ();
+ this->timer_for_context_switch.get_rusage (this->usage);
+# if defined (ACE_HAS_PRUSAGE_T)
+ this->context_switch_ = this->usage.pr_vctx + this->usage.pr_ictx;
+# else /* ACE_HAS_PRUSAGE_T */
+ this->context_switch_ = this->usage.ru_nvcsw + this->usage.ru_nivcsw;
+# endif /* ACE_HAS_GETRUSAGE */
+ }
+#endif /* ACE_HAS_PRUSAGE_T || ACE_HAS_GETRUSAGE */
+
+#if defined (ACE_VXWORKS) && !defined (__RTP__) && !defined (ACE_HAS_PTHREADS)
+ if (this->ts_->context_switch_test_ == 1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Adding the context switch hook!\n"));
+ taskSwitchHookAdd ((FUNCPTR) &switchHook);
+ }
+#endif /* ACE_VXWORKS && !__RTP__ */
+}
+
+void
+Client_i::output_latency (void)
+{
+ FILE *latency_file_handle = 0;
+ char latency_file[BUFSIZ];
+ char buffer[BUFSIZ];
+
+ ACE_OS::sprintf (latency_file,
+ "c%d",
+ this->ts_->thread_count_);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "--->Output file for latency data is \"%s\"\n",
+ latency_file));
+
+ latency_file_handle = ACE_OS::fopen (latency_file, "w");
+
+ // This loop visits each client. thread_count_ is the number of
+ // clients.
+ for (u_int j = 0;
+ j < this->ts_->thread_count_;
+ ++j)
+ {
+ ACE_OS::sprintf(buffer,
+ "%s #%d",
+ j == 0
+ ? "High Priority"
+ : "Low Priority",
+ j);
+ // This loop visits each request latency from a client.
+ JITTER_ARRAY_ITERATOR iterator =
+ this->ts_->global_jitter_array_ [j]->begin ();
+
+ u_int i = 0;
+ ACE_timer_t *latency = 0;
+
+ for (iterator.first ();
+ (i < (j == 0
+ ? this->ts_->high_priority_loop_count_
+ : this->ts_->loop_count_) / this->ts_->granularity_) &&
+ (iterator.next (latency));
+ i++,iterator.advance ())
+ {
+ ACE_OS::sprintf (buffer + ACE_OS::strlen (buffer),
+#if defined (CHORUS_MVME)
+ "\t%u\n",
+#else
+ "\t%f\n",
+#endif /* !CHORUS_MVME */
+ *latency);
+ ACE_OS::fputs (buffer,
+ latency_file_handle);
+ buffer[0] = 0;
+ }
+ }
+
+ ACE_OS::fclose (latency_file_handle);
+}
+
+// Mechanism to distribute the available priorities among the threads
+// when there are not enough different priorities for all threads.
+
+void
+Client_i::init_low_priority (void)
+{
+ ACE_Sched_Priority prev_priority = this->high_priority_;
+ if (this->ts_->use_multiple_priority_ == 1)
+ this->low_priority_ =
+ this->priority_.get_low_priority (this->num_low_priority_,
+ prev_priority,
+ 1);
+ else
+ this->low_priority_ =
+ this->priority_.get_low_priority (this->num_low_priority_,
+ prev_priority,
+ 0);
+ this->num_priorities_ =
+ this->priority_.number_of_priorities ();
+ this->grain_ = this->priority_.grain ();
+ this->counter_ = 0;
+}
+
+void
+Client_i::calc_util_time (void)
+{
+ MT_Cubit_Timer timer (ACE_ONE_SECOND_IN_MSECS);
+ // Time the utilization thread' "computation" to get % IdleCPU at the
+ // end of the test.
+
+ // Execute one computation.
+ timer.start ();
+#if defined (CHORUS_MVME)
+ this->util_thread_->computation ();
+ timer.stop ();
+ this->util_task_duration_ = timer.get_elapsed ();
+#else
+ for (u_int i = 0;
+ i < NUM_UTIL_COMPUTATIONS;
+ ++i)
+ this->util_thread_->computation ();
+
+ timer.stop ();
+ this->util_task_duration_ = timer.get_elapsed () / NUM_UTIL_COMPUTATIONS;
+#endif /* !CHORUS_MVME */
+}
+
+int
+Client_i::activate_high_client (void)
+{
+ ACE_NEW_RETURN (this->high_priority_client_,
+ Client (&this->client_thread_manager_,
+ this->ts_,
+ this->argc_,
+ this->argv_,
+ 0),
+ -1);
+
+#if defined (ACE_VXWORKS)
+ // Set a task_id string starting with "@", so we are able to
+ // accurately count the number of context switches.
+ ACE_OS::strcpy (this->task_id_,
+ "@High");
+#endif /* ACE_VXWORKS */
+
+ this->high_priority_ =
+ this->priority_.get_high_priority ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating 1 client with high priority of %d\n",
+ this->high_priority_));
+ if (this->high_priority_client_->activate (
+ GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 0,
+ this->high_priority_,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ (ACE_thread_t *) &this->task_id_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p; priority is %d\n",
+ "activate failed",
+ this->high_priority_),
+ -1);
+ return 0;
+}
+
+int
+Client_i::activate_low_client (void)
+{
+ ACE_NEW_RETURN (this->low_priority_client_,
+ Client *[this->ts_->thread_count_],
+ -1);
+
+ // Hack to make sure we have something in this pointer, when
+ // thread_count == 1.
+ this->low_priority_client_[0] =
+ this->high_priority_client_;
+ this->num_low_priority_ =
+ this->ts_->thread_count_ - 1;
+
+ // Set the priority for the low priority threads.
+ this->init_low_priority ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating %d clients at priority %d\n",
+ this->ts_->thread_count_ - 1,
+ this->low_priority_));
+
+ for (u_int i = this->num_low_priority_;
+ i > 0;
+ i--)
+ {
+ ACE_NEW_RETURN (this->low_priority_client_ [i - 1],
+ Client (&this->client_thread_manager_,
+ this->ts_,
+ this->argc_,
+ this->argv_,
+ i),
+ -1);
+#if defined (ACE_VXWORKS)
+ // Pace the connection establishment on VxWorks.
+ const ACE_Time_Value delay (0L, 500000L);
+ ACE_OS::sleep (delay);
+
+ // Set a task_id string startiing with "@", so we are able to
+ // accurately count the number of context switches on VXWORKS
+ sprintf (this->task_id_,
+ "@Low%u",
+ i);
+#endif /* ACE_VXWORKS */
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating client with thread ID %d and priority %d\n",
+ i,
+ this->low_priority_));
+ // The first thread starts at the lowest priority of all the low
+ // priority clients.
+ if (this->low_priority_client_[i - 1]->activate (
+ GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 0,
+ this->low_priority_, // These are constructor defaults.
+ -1, // int grp_id = -1,
+ 0, // ACE_Task_Base *task = 0,
+ 0, // ACE_hthread_t thread_handles[] = 0,
+ 0, // void *stack[] = 0,
+ 0, // size_t stack_size[] = 0,
+ (ACE_thread_t *) &this->task_id_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p; priority is %d\n",
+ "activate failed",
+ this->low_priority_));
+
+ if (this->ts_->use_multiple_priority_ == 1)
+ {
+ this->counter_ = (this->counter_ + 1) % this->grain_;
+
+ if (this->counter_ == 0
+ // Just so when we distribute the priorities among the
+ // threads, we make sure we don't go overboard.
+ && this->num_priorities_ * this->grain_ > this->num_low_priority_ - (i - 1))
+ // Get the next higher priority.
+ this->low_priority_ = ACE_Sched_Params::next_priority
+ (ACE_SCHED_FIFO, this->low_priority_, ACE_SCOPE_THREAD);
+ }
+ } /* end of for () */
+
+ return 0;
+}
+
+int
+Client_i::activate_util_thread (void)
+{
+ ACE_NEW_RETURN (this->util_thread_,
+ Util_Thread (this->ts_,
+ &this->util_thread_manager_),
+ -1);
+
+ // Time the utilization thread' "computation" to get %IdleCPU at the
+ // end of the test.
+ this->calc_util_time ();
+
+ if (this->ts_->use_utilization_test_ == 1)
+ // Activate the utilization thread only if specified. See
+ // description of this variable in header file.
+ {
+ this->low_priority_ =
+ ACE_Sched_Params::priority_min (ACE_SCHED_FIFO,
+ ACE_SCOPE_THREAD);
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating utilization thread with priority of %d\n",
+ this->low_priority_));
+
+ // Activate the Utilization thread. It will wait until all
+ // threads have finished binding.
+ this->util_thread_->activate (
+ GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 0,
+ this->low_priority_);
+ }
+ else
+ this->util_thread_->close ();
+ return 0;
+}
+
+void
+Client_i:: print_context_stats (void)
+{
+ if (this->ts_->context_switch_test_ == 1)
+ {
+#if defined (ACE_HAS_PRUSAGE_T)
+ this->timer_for_context_switch.stop ();
+ this->timer_for_context_switch.get_rusage (this->usage);
+ // Add up the voluntary context switches & involuntary context
+ // switches.
+ this->context_switch_ =
+ this->usage.pr_vctx + this->usage.pr_ictx - this->context_switch_;
+ ACE_DEBUG ((LM_DEBUG,
+ "Voluntary context switches = %d, Involuntary context switches = %d\n",
+ this->usage.pr_vctx,
+ this->usage.pr_ictx));
+#elif defined (ACE_HAS_GETRUSAGE) && !defined (ACE_WIN32)
+ this->timer_for_context_switch.stop ();
+ this->timer_for_context_switch.get_rusage (this->usage);
+ // Add up the voluntary context switches & involuntary context
+ // switches.
+ this->context_switch_ =
+ this->usage.ru_nvcsw + this->usage.ru_nivcsw - this->context_switch_;
+ ACE_DEBUG ((LM_DEBUG,
+ "Voluntary context switches=%d, Involuntary context switches=%d\n",
+ this->usage.ru_nvcsw,
+ this->usage.ru_nivcsw));
+#elif defined (ACE_VXWORKS) && !defined (__RTP__) && !defined (ACE_HAS_PTHREADS)
+ taskSwitchHookDelete ((FUNCPTR) &switchHook);
+ ACE_DEBUG ((LM_DEBUG,
+ "Context switches=%d\n",
+ ctx));
+#endif /* ACE_HAS_PRUSAGE_T */
+ }
+}
+
+void
+Client_i::print_latency_stats (void)
+{
+ // If running the utilization test, don't report latency nor jitter.
+ if (this->ts_->use_utilization_test_ == 0)
+ {
+#if defined (ACE_VXWORKS)
+ ACE_DEBUG ((LM_DEBUG,
+ "Test done.\n"
+ "High priority client latency : %f usec, jitter: %f usec\n"
+ "Low priority client latency : %f usec, jitter: %f usec\n",
+ this->high_priority_client_->get_high_priority_latency (),
+ this->high_priority_client_->get_high_priority_jitter (),
+ this->low_priority_client_[0]->get_low_priority_latency (),
+ this->low_priority_client_[0]->get_low_priority_jitter ()));
+ // Output the latency values to a file, tab separated, to import
+ // it to Excel to calculate jitter, in the mean time we come up
+ // with the sqrt() function.
+ output_latency ();
+#elif defined (CHORUS_MVME)
+ ACE_DEBUG ((LM_DEBUG,
+ "Test done.\n"
+ "High priority client latency : %u usec\n"
+ "Low priority client latency : %u usec\n",
+ this->high_priority_client_->get_high_priority_latency (),
+ this->low_priority_client_[0]->get_low_priority_latency () ));
+ // Output the latency values to a file, tab separated, to import
+ // it to Excel to calculate jitter, in the mean time we come up
+ // with the sqrt() function.
+ output_latency ();
+#else /* !CHORUS_MVME */
+ ACE_DEBUG ((LM_DEBUG, "Test done.\n"
+ "High priority client latency : %f usec, jitter: %f usec\n"
+ "Low priority client latency : %f usec, jitter: %f usec\n",
+ this->high_priority_client_->get_high_priority_latency (),
+ this->high_priority_client_->get_high_priority_jitter (),
+ this->low_priority_client_[0]->get_low_priority_latency (),
+ this->low_priority_client_[0]->get_low_priority_jitter ()));
+ // output_latency ();
+#endif /* !ACE_VXWORKS && !CHORUS_MVME */
+ }
+}
+
+void
+Client_i::print_util_stats (void)
+{
+ if (this->ts_->use_utilization_test_ == 1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Scavenger task performed \t%u computations\n"
+ "(%t) CLIENT task performed \t\t%u %s calls as requested\n\n"
+ "(%t) Utilization test time is \t\t%f microseconds\n\t%s\n",
+ this->util_thread_->get_number_of_computations (),
+ this->ts_->loop_count_,
+ this->ts_->remote_invocations_ == 1 ? "CORBA" : "local",
+ this->ts_->util_test_time_,
+ this->ts_->remote_invocations_ == 1 ?
+ "NOW run the same test again, adding the \"-l\" option. See README file for explanation." :
+ " "
+ ));
+ }
+}
+
+void
+Client_i::print_priority_inversion_stats (void)
+{
+ this->print_context_stats ();
+ this->print_latency_stats ();
+ this->print_util_stats ();
+}
+
+int
+Client_i::start_servant (void)
+{
+ char high_thread_args[BUFSIZ];
+
+ ACE_OS::sprintf (high_thread_args,
+ "-ORBSndSock 32768 "
+ "-ORBRcvSock 32768 ");
+
+ Cubit_Task *high_priority_task;
+
+ ACE_NEW_RETURN (high_priority_task,
+ Cubit_Task ((const char *) high_thread_args,
+ (const char *) "internet",
+ (u_int) 1,
+ &this->server_thread_manager_,
+ (u_int) 0), // task id 0.
+ -1);
+
+ this->high_priority_ =
+ this->priority_.get_high_priority ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating servant 0 with high priority %d\n",
+ this->high_priority_));
+
+ // Make the high priority task an active object.
+ if (high_priority_task->activate (
+ GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 0,
+ this->high_priority_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "\thigh_priority_task->activate failed"));
+
+ ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ready_mon, GLOBALS::instance ()->ready_mtx_,-1));
+
+ // Wait on the condition variable till the high priority cubit_task
+ // has finished argument processing.
+ while (!GLOBALS::instance ()->ready_)
+ GLOBALS::instance ()->ready_cnd_.wait ();
+ // wait on the barrier till the servant writes its ior.
+ GLOBALS::instance ()->barrier_->wait ();
+
+ this->ts_->one_ior_ =
+ high_priority_task->get_servant_ior (0);
+
+ return 0;
+}
+
+int
+Client_i::do_priority_inversion_test (void)
+{
+ this->timer_.start ();
+#if defined (ACE_VXWORKS)
+# if !defined (__RTP__) && !defined (ACE_HAS_PTHREADS)
+ ctx = 0;
+# endif
+ ACE_NEW_RETURN (this->task_id_,
+ char[TASK_ID_LEN],
+ -1);
+#endif /* ACE_VXWORKS */
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) <<<<<<< starting test on %D\n"));
+ GLOBALS::instance ()->num_of_objs = 1;
+
+ for (int j = 0; j < this->argc_; j++)
+ if (ACE_OS::strcmp (this->argv_[j], "-u") == 0)
+ {
+ this->start_servant ();
+ break;
+ }
+ // Create and activate the high priority client.
+ int result = this->activate_high_client ();
+ if (result < 0)
+ return result;
+
+ ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ready_mon, this->ts_->ready_mtx_,-1));
+
+ // Wait on the condition variable until the high priority thread
+ // wakes us up.
+ while (!this->ts_->ready_)
+ this->ts_->ready_cnd_.wait ();
+
+ result = this->activate_low_client ();
+
+ if (result < 0)
+ return result;
+
+ // Activate the utilization thread if necessary.
+ result = this->activate_util_thread ();
+ if (result < 0)
+ return result;
+
+ // Wait for all the client threads to be initialized before going
+ // any further.
+ this->ts_->barrier_->wait ();
+
+ STOP_QUANTIFY;
+ CLEAR_QUANTIFY;
+
+ // Collect the context switch data.
+ this->get_context_switches ();
+
+ // Wait for all the client threads to exit (except the utilization
+ // thread).
+ this->client_thread_manager_.wait ();
+
+ STOP_QUANTIFY;
+ ACE_DEBUG ((LM_DEBUG,"(%P|%t) >>>>>>> ending test on %D\n"));
+
+ this->timer_.stop ();
+ this->timer_.elapsed_time (this->delta_);
+
+ // Signal the utilization thread to finish with its work.. only if
+ // utilization test was specified. See description of this variable
+ // in header file.
+ if (this->ts_->use_utilization_test_ == 1)
+ {
+ this->util_thread_->done_ = 1;
+
+ // This will wait for the utilization thread to finish.
+ this->util_thread_manager_.wait ();
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "-------------------------- Stats -------------------------------\n"));
+
+ this->print_priority_inversion_stats ();
+
+ return 0;
+}
+
+int
+Client_i::do_thread_per_rate_test (void)
+{
+ Client CB_20Hz_client (&this->client_thread_manager_,
+ this->ts_,
+ this->argc_,
+ this->argv_,
+ CB_20HZ_CONSUMER);
+ Client CB_10Hz_client (&this->client_thread_manager_,
+ this->ts_,
+ this->argc_,
+ this->argv_,
+ CB_10HZ_CONSUMER);
+ Client CB_5Hz_client (&this->client_thread_manager_,
+ this->ts_,
+ this->argc_,
+ this->argv_,
+ CB_5HZ_CONSUMER);
+ Client CB_1Hz_client (&this->client_thread_manager_,
+ this->ts_,
+ this->argc_,
+ this->argv_,
+ CB_1HZ_CONSUMER);
+ ACE_Sched_Priority priority;
+
+ priority = this->priority_.get_high_priority ();
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating 20 Hz client with priority %d\n",
+ priority));
+
+ if (CB_20Hz_client.activate (
+ GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 1,
+ priority) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) errno = %p: activate failed\n"));
+ // The high priority thread is parsing the arguments, so wait on the
+ // condition variable until it wakes us up.
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Waiting for argument parsing\n"));
+
+ ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, ready_mon, this->ts_->ready_mtx_,-1));
+
+ // Wait on the condition variable until the high priority thread
+ // wakes us up.
+ while (!this->ts_->ready_)
+ this->ts_->ready_cnd_.wait ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Argument parsing waiting done\n"));
+
+ priority = ACE_Sched_Params::previous_priority (ACE_SCHED_FIFO,
+ priority,
+ ACE_SCOPE_THREAD);
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating 10 Hz client with priority %d\n",
+ priority));
+
+ if (CB_10Hz_client.activate (
+ GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 1,
+ priority) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) errno = %p: activate failed\n"));
+
+ priority = ACE_Sched_Params::previous_priority (ACE_SCHED_FIFO,
+ priority,
+ ACE_SCOPE_THREAD);
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating 5 Hz client with priority %d\n",
+ priority));
+
+ if (CB_5Hz_client.activate (
+ GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 1,
+ priority) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) errno = %p: activate failed\n"));
+
+ priority = ACE_Sched_Params::previous_priority (ACE_SCHED_FIFO,
+ priority,
+ ACE_SCOPE_THREAD);
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating 1 Hz client with priority %d\n",
+ priority));
+
+ if (CB_1Hz_client.activate (
+ GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 1,
+ priority) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) errno = %p: activate failed\n"));
+
+ // Wait for all the threads to exit.
+ this->client_thread_manager_.wait ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Test done.\n"
+ "20Hz client latency : %A usec, jitter: %A usec\n"
+ "10Hz client latency : %A usec, jitter: %A usec\n"
+ "5Hz client latency : %A usec, jitter: %A usec\n"
+ "1Hz client latency : %A usec, jitter: %A usec\n",
+ CB_20Hz_client.get_latency (0),
+ CB_20Hz_client.get_jitter (0),
+ CB_10Hz_client.get_latency (1),
+ CB_10Hz_client.get_jitter (1),
+ CB_5Hz_client.get_latency (2),
+ CB_5Hz_client.get_jitter (2),
+ CB_1Hz_client.get_latency (3),
+ CB_1Hz_client.get_jitter (3) ));
+ return 0;
+}
+
+// This is the main routine of the client, where we create a high
+// priority and a low priority client. we then activate the clients
+// with the appropriate priority threads, and wait for them to
+// finish. After they aer done, we compute the latency and jitter
+// metrics and print them.
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Log_Msg::instance()->clr_flags (ACE_Log_Msg::LOGGER);
+
+ Client_i client;
+
+ int result = client.init (argc,argv);
+
+ if (result < 0)
+ return result;
+
+ // Run the tests.
+ client.run ();
+
+#if defined (CHORUS_MVME)
+ int pTime;
+ if (pccTimer (PCC2_TIMER1_STOP,
+ &pTime) != K_OK)
+ ACE_DEBUG ((LM_DEBUG,
+ "pccTimer has a pending bench mark\n"));
+#endif /* CHORUS_MVME */
+ return 0;
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h
new file mode 100644
index 00000000000..263c3474e42
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/client.h
@@ -0,0 +1,183 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// client.h
+//
+// = AUTHOR
+// Andy Gokhale, Brian Mendel, Sumedh Mungee, Sergio Flores-Gaitan
+// and Nagarajan Surendran.
+//
+// ============================================================================
+
+#include "ace/Task.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Thread_Manager.h"
+#include "ace/Get_Opt.h"
+#include "ace/Sched_Params.h"
+
+#include "cubitC.h"
+#include "Task_Client.h"
+#include "Util_Thread.h"
+#include "Timer.h"
+
+#if defined (CHORUS_MVME)
+#include "pccTimer.h"
+#endif /* CHORUS_MVME */
+
+#if defined (VME_DRIVER)
+#include <hostLib.h>
+extern "C" STATUS vmeDrv (void);
+extern "C" STATUS vmeDevCreate (char *);
+#endif /* defined (VME_DRIVER) */
+
+class Client_i : public virtual MT_Priority
+{
+ // = TITLE
+ // Helper class implementing the Multi-Threaded Cubit client.
+public:
+ Client_i (void);
+ //constructor.
+
+ virtual ~Client_i (void);
+ // destructor.
+
+ int init (int argc, char *argv[]);
+ // Initialize the state of <Client_i>.
+
+ void run (void);
+ // Run the tests.
+
+ int do_priority_inversion_test (void);
+ // Performs the priority inversion test.
+
+ int do_thread_per_rate_test (void);
+ // Performs the test with 4 threads each sending requests at rates
+ // of 20, 10, 5, and 1Hz.
+
+ int start_servant (void);
+ // Starts the client utilization thread.
+
+ void output_latency (void);
+ // output the latency results for the requests.
+
+#if defined (VXWORKS)
+ void output_taskinfo (void);
+ // Outputs the details of this task to a file taskinfo.txt.
+#endif /* VXWORKS */
+
+private:
+ void init_low_priority (void);
+ // Sets the priority to be used for the low priority clients.
+
+ void calc_util_time (void);
+ // Calculate the time for one util computation.
+
+ int activate_high_client (void);
+ // Activates the high priority client.
+
+ int activate_low_client (void);
+ // Activates the low priority client.
+
+ int activate_util_thread (void);
+ // Activates the utilization thread.
+
+ void print_priority_inversion_stats (void);
+ // Prints the results of the tests.
+
+ void print_context_stats (void);
+ // Prints the context switch results.
+
+ void print_util_stats (void);
+ // Prints the utilization test results.
+
+ void print_latency_stats (void);
+ // Prints the latency and jitter results.
+
+ void get_context_switches (void);
+ // gets the number of context switches.
+
+ Client *high_priority_client_;
+ // Pointer to the high priority client object.
+
+ Client **low_priority_client_;
+ // Array to hold pointers to the low priority tasks.
+
+ ACE_High_Res_Timer timer_;
+ // Timer for timing the tests.
+
+ MT_Priority priority_;
+ // Priority helper object.
+
+ Util_Thread *util_thread_;
+ // Utilization thread.
+
+ ACE_Thread_Manager util_thread_manager_;
+ // Utilization thread manager.
+
+ ACE_timer_t util_task_duration_;
+ // Time for one computation of utilization thread.
+
+ Task_State *ts_;
+ // Pointer to task state.
+
+ ACE_Sched_Priority high_priority_;
+ // Priority used for the high priority client.
+
+ ACE_Sched_Priority low_priority_;
+ // Priority used by the low priority clients.
+
+ u_int num_low_priority_;
+ // Number of low priority clients
+
+ u_int num_priorities_;
+ // Number of priorities used.
+
+ u_int grain_;
+ // Granularity of the assignment of the priorities. Some OSs have
+ // fewer levels of priorities than we have threads in our test, so
+ // with this mechanism we assign priorities to groups of threads
+ // when there are more threads than priorities.
+
+ u_int counter_;
+ // counter of the number of priorities used within a grain.
+
+ char *task_id_;
+ // Set a task_id string starting with "@", so we are able to
+ // accurately count the number of context switches.
+
+ ACE_Time_Value delta_;
+ // elapsed time for the latency tests.
+
+ int argc_;
+ // number of command line arguments.
+
+ char **argv_;
+ // command line argument array.
+
+ ACE_Thread_Manager client_thread_manager_;
+ // Create a separate manager for the client. This allows the use of
+ // its wait () method on VxWorks, without interfering with the
+ // server's (global) thread manager.
+
+ u_int context_switch_;
+ // Stores the total number of context switches incurred by the
+ // program while making CORBA requests
+
+ ACE_Thread_Manager server_thread_manager_;
+ // Thread manager for the servant used for utilization.
+
+#if (defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)) && !defined (ACE_WIN32)
+ ACE_Profile_Timer timer_for_context_switch;
+ ACE_Profile_Timer::Rusage usage;
+#endif /* (defined (ACE_HAS_PRUSAGE_T) || defined (ACE_HAS_GETRUSAGE)) && !defined (ACE_WIN32) */
+};
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit.idl b/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit.idl
new file mode 100644
index 00000000000..30285cd9d12
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit.idl
@@ -0,0 +1,39 @@
+// $Id$
+
+interface Cubit
+{
+ // = TITLE
+ // Defines an interface that encapsulates operations that cube
+ // numbers.
+ //
+ // = DESCRIPTION
+ // This interface encapsulates operations that cube
+ // octets, shorts, longs, structs and unions.
+
+ struct Many
+ {
+ octet o; // + 3 bytes padding (normally) ...
+ long l;
+ short s; // + 2 bytes padding (normally) ...
+ };
+
+ octet cube_octet (in octet o);
+ // Cube an octet.
+
+ short cube_short (in short s);
+ // Cube a short.
+
+ long cube_long (in long l);
+ // Cube a long.
+
+ Many cube_struct (in Many values);
+ // Cube each of the members of a struct.
+
+ oneway void noop ();
+ // Null operation.
+
+ oneway void shutdown ();
+ // shut down the application
+
+};
+
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit_i.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit_i.cpp
new file mode 100644
index 00000000000..cd3adaaf7ca
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit_i.cpp
@@ -0,0 +1,77 @@
+// $Id$
+
+#include "tao/ORB_Constants.h"
+#include "cubit_i.h"
+#include "Task_Client.h"
+
+ACE_RCSID(MT_Cubit, cubit_i, "$Id$")
+
+Cubit_i::Cubit_i (CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa)
+ : orb_ (CORBA::ORB::_duplicate (orb)),
+ poa_ (PortableServer::POA::_duplicate (poa))
+{
+}
+
+Cubit_i::~Cubit_i (void)
+{
+}
+
+CORBA::Octet
+Cubit_i::cube_octet (CORBA::Octet o
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return (CORBA::Octet) (o * o * o);
+}
+
+CORBA::Short
+Cubit_i::cube_short (CORBA::Short s
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return (CORBA::Short) (s * s * s);
+}
+
+CORBA::Long
+Cubit_i::cube_long (CORBA::Long l
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return (CORBA::Long) (l * l * l);
+}
+
+Cubit::Many
+Cubit_i::cube_struct (const Cubit::Many &values
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ Cubit::Many out_values;
+
+ out_values.o = values.o * values.o * values.o;
+ out_values.s = values.s * values.s * values.s;
+ out_values.l = values.l * values.l * values.l;
+
+ return out_values;
+}
+
+void
+Cubit_i::noop (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // does nothing.
+}
+
+void Cubit_i::shutdown (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Calling orb ()->shutdown ()\n"));
+ this->orb_->shutdown ();
+}
+
+PortableServer::POA_ptr
+Cubit_i::_default_POA (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+{
+ return PortableServer::POA::_duplicate (this->poa_.in ());
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit_i.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit_i.h
new file mode 100644
index 00000000000..eaa646cfb06
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/cubit_i.h
@@ -0,0 +1,66 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// cubit_i.h
+//
+// = AUTHOR
+// Andy Gokhale, Sumedh Mungee, Sergio Flores-Gaitan and Nagarajan Surendran.
+//
+// ============================================================================
+
+#ifndef _CUBIT_I_H
+#define _CUBIT_I_H
+
+#include "cubitS.h"
+
+class Cubit_i : public POA_Cubit
+{
+ // = TITLE
+ // Cubit implementation class.
+public:
+ // = Initialization and termination methods.
+ Cubit_i (CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa);
+ ~Cubit_i (void);
+
+ virtual CORBA::Octet cube_octet (CORBA::Octet o
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual CORBA::Short cube_short (CORBA::Short s
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual CORBA::Long cube_long (CORBA::Long l
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual Cubit::Many cube_struct (const Cubit::Many &values
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void noop (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void shutdown (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual PortableServer::POA_ptr
+ _default_POA (ACE_ENV_SINGLE_ARG_DECL);
+ // The default POA
+
+protected:
+ CORBA::ORB_var orb_;
+ // Keep a pointer to the ORB so we can shut it down.
+
+ PortableServer::POA_var poa_;
+ // The default POA..
+};
+
+#endif /* _CUBIT_I_H */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/plot b/TAO/performance-tests/Cubit/TAO/MT_Cubit/plot
new file mode 100755
index 00000000000..d83cc92e988
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/plot
@@ -0,0 +1,50 @@
+eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}'
+ & eval 'exec perl -w -S $0 $argv:q'
+ if 0;
+
+# $Id$
+#
+# Plots output from summarize.
+
+open (HIGH_LATENCY, "> h") || die "$0: unable to open \"h\"";
+open (LOW_LATENCY, "> l") || die "$0: unable to open \"l\"";
+
+while (<>) {
+ if (/([\d\.]+) +([\d\.]+) +([\d\.]+) +([\d\.]+) +([\d\.]+)/) {
+ $low_priority_threads = $1;
+ $high_latency = $2;
+ $high_jitter = $3;
+ $low_latency = $4;
+ $low_jitter = $5;
+ print HIGH_LATENCY "$low_priority_threads $high_latency $high_jitter\n";
+ if ($low_priority_threads > 0) {
+ print LOW_LATENCY "$low_priority_threads $low_latency $low_jitter\n";
+ }
+ }
+}
+
+close HIGH_LATENCY;
+close LOW_LATENCY;
+
+open (GNUPLOT, "| gnuplot") || die "unable to open \"gnuplot\"\n";
+
+print GNUPLOT
+ "set terminal postscript eps color\n" .
+ "set output \"/dev/null\"\n" .
+ "set yrange [0:]\n" .
+ "set grid ytics\n" .
+ "set xlabel \"Number of Low priority Clients\"\n" .
+ "set ylabel \"Latency per two-way request, microseconds\n" .
+ "set linestyle 1 linetype 2 pointtype 2\n" .
+ "set linestyle 2 linetype 1 pointtype 1\n" .
+ " plot 'l' title \"Low Priority Clients\" with linespoints ls 2\n" .
+ "replot 'h' title \"High Priority Client\" with linespoints ls 1\n" .
+ "set yrange [] writeback\n" .
+ "replot 'h' notitle with errorbars ls 1\n" .
+ "set output \"plot.eps\"\n" .
+ "set noautoscale y\n" .
+ "replot 'l' notitle with errorbars ls 2\n";
+
+close GNUPLOT;
+
+unlink 'h', 'l';
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/run_test.pl b/TAO/performance-tests/Cubit/TAO/MT_Cubit/run_test.pl
new file mode 100755
index 00000000000..559bdaac458
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/run_test.pl
@@ -0,0 +1,74 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+$usage = "run_tests.pl [-n iterations] [-r, for thread-per-rate] [-t low priority threads]\n";
+
+use lib "../../../../../bin";
+use PerlACE::Run_Test;
+
+$iorfile = PerlACE::LocalFile ("mtcubit.ior");
+$iterations = 1000;
+$low_priority_threads = 1;
+$thread_per_rate = '';
+
+####
+#### Process command line args.
+####
+while ($#ARGV >= $[ && $ARGV[0] =~ /^-/) {
+ if ($ARGV[0] eq '-n') {
+ if ($ARGV[1] =~ /^[\da-zA-Z]+$/) {
+ $iterations = $ARGV[1]; shift;
+ } else {
+ print STDERR "$0: must provide argument for -n option\n";
+ die $usage;
+ }
+ } elsif ($ARGV[0] eq '-r') {
+ $thread_per_rate = '-r';
+ } elsif ($ARGV[0] eq '-t') {
+ if ($ARGV[1] =~ /^[\da-zA-Z]+$/) {
+ $low_priority_threads = $ARGV[1]; shift;
+ } else {
+ print STDERR "$0: must provide argument for -n option\n";
+ die $usage;
+ }
+ } elsif ($ARGV[0] eq '-?') {
+ print "$usage";
+ exit;
+ } else {
+ print STDERR "$0: unknown option $ARGV[0]\n";
+ die $usage;
+ }
+ shift;
+}
+
+$threads = $low_priority_threads + 1;
+
+# Make sure the file is gone, so we can wait on it.
+unlink $iorfile;
+
+$SV = new PerlACE::Process ("server", "$thread_per_rate -f $iorfile -t $threads");
+$CL = new PerlACE::Process ("client", "$thread_per_rate -f $iorfile -t $threads -n $iterations");
+
+$SV->Spawn ();
+
+if (PerlACE::waitforfile_timed ($iorfile, 10) == -1) {
+ print STDERR "ERROR: cannot find file <$iorfile>\n";
+ $SV->Kill ();
+ exit 1;
+}
+
+$client = $CL->SpawnWaitKill (180);
+$SV->Kill ();
+
+unlink $iorfile;
+
+if ($client != 0) {
+ print STDERR "ERROR: client returned $client\n";
+ exit 1;
+}
+
+exit 0;
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp b/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp
new file mode 100644
index 00000000000..9235f275e82
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.cpp
@@ -0,0 +1,394 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// server.cpp
+//
+// = AUTHOR
+// Andy Gokhale,
+// Sumedh Mungee,
+// Sergio Flores-Gaitan, and
+// Nagarajan Surendran
+//
+// ============================================================================
+
+#include "ace/config-all.h"
+
+#if defined (ACE_VXWORKS) && !defined (__RTP__)
+# undef ACE_MAIN
+# define ACE_MAIN server
+#endif /* ACE_VXWORKS && !__RTP__ */
+
+#include "server.h"
+#include "ace/Sched_Params.h"
+#include "tao/Strategies/advanced_resource.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Barrier.h"
+
+#if defined (ACE_HAS_QUANTIFY)
+# include "quantify.h"
+#endif /* ACE_HAS_QUANTIFY */
+
+ACE_RCSID(MT_Cubit, server, "$Id$")
+
+Server::Server (void)
+ :argc_ (0),
+ argv_ (0),
+ cubits_ (0),
+ high_priority_task_ (0),
+ low_priority_tasks_ (0),
+ high_argv_ (0),
+ low_argv_ (0)
+{
+}
+
+int
+Server::init (int argc, char **argv)
+{
+ int result;
+
+ result = GLOBALS::instance ()->sched_fifo_init ();
+ if (result == -1)
+ return result;
+
+ this->argc_ = argc;
+ this->argv_ = argv;
+
+ VX_VME_INIT;
+ FORCE_ARGV (this->argc_,this->argv_);
+ // Make sure we've got plenty of socket handles. This call will use
+ // the default maximum.
+ ACE::set_handle_limit ();
+ return 0;
+}
+
+int
+Server::run (void)
+{
+ STOP_QUANTIFY;
+ CLEAR_QUANTIFY;
+ START_QUANTIFY;
+
+ if (this->start_servants () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error creating the servants\n"),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ "Wait for all the threads to exit\n"));
+ // Wait for all the threads to exit.
+ this->servant_manager_.wait ();
+ STOP_QUANTIFY;
+ return 0;
+}
+
+void
+Server::prelim_args_process (void)
+{
+ int i;
+
+ for (i = 0; i < this->argc_ ; i++)
+ {
+ if (ACE_OS::strcmp (this->argv_[i], "-e") == 0 &&
+ i - 1 < this->argc_)
+ ACE_OS::strcpy (GLOBALS::instance ()->endpoint,
+ this->argv_[i+1]);
+ }
+}
+
+void
+Server::init_low_priority (void)
+{
+ ACE_Sched_Priority prev_priority = this->high_priority_;
+
+ // Drop the priority.
+ if (GLOBALS::instance ()->thread_per_rate == 1
+ || GLOBALS::instance ()->use_multiple_priority == 1)
+ this->low_priority_ =
+ this->priority_.get_low_priority (this->num_low_priority_,
+ prev_priority,
+ 1);
+ else
+ this->low_priority_ =
+ this->priority_.get_low_priority (this->num_low_priority_,
+ prev_priority,
+ 0);
+
+ this->num_priorities_ = this->priority_.number_of_priorities ();
+ this->grain_ = this->priority_.grain ();
+ this->counter_ = 0;
+}
+
+// Write the ior's to a file so the client can read them.
+
+int
+Server::write_iors (void)
+{
+ u_int j;
+
+ // By this time the num of objs should be set properly.
+ ACE_NEW_RETURN (this->cubits_,
+ char* [GLOBALS::instance ()->num_of_objs],
+ -1);
+
+ this->cubits_[0] = ACE_OS::strdup (this->high_priority_task_->get_servant_ior (0));
+
+ for (j = 1;
+ j < GLOBALS::instance ()->num_of_objs;
+ ++j)
+ this->cubits_[j] =
+ ACE_OS::strdup (this->low_priority_tasks_[j-1]->get_servant_ior (0));
+
+ FILE *ior_f = 0;
+
+ if (GLOBALS::instance ()->ior_file != 0)
+ ior_f = ACE_OS::fopen (GLOBALS::instance ()->ior_file,
+ "w");
+
+ for (j = 0;
+ j < GLOBALS::instance ()->num_of_objs;
+ ++j)
+ {
+ if (ior_f != 0)
+ {
+ ACE_OS::fprintf (ior_f,
+ "%s\n",
+ this->cubits_[j]);
+ ACE_DEBUG ((LM_DEBUG,
+ "this->cubits_[%d] ior = %s\n",
+ j,
+ this->cubits_[j]));
+ }
+ }
+
+ if (ior_f != 0)
+ ACE_OS::fclose (ior_f);
+
+ return 0;
+}
+
+int
+Server::activate_high_servant (void)
+{
+ char orbendpoint[BUFSIZ];
+
+ ACE_OS::sprintf (orbendpoint,
+ "-ORBEndpoint %s ",
+ GLOBALS::instance ()->endpoint);
+
+ char *high_second_argv[] =
+ {orbendpoint,
+ const_cast<char *> ("-ORBSndSock 32768 "),
+ const_cast<char *> ("-ORBRcvSock 32768 "),
+ 0};
+ ACE_NEW_RETURN (this->high_argv_,
+ ACE_ARGV (this->argv_, high_second_argv),
+ -1);
+ ACE_NEW_RETURN (this->high_priority_task_,
+ Cubit_Task (this->high_argv_->buf (),
+ "internet",
+ 1,
+ &this->servant_manager_,
+ 0), //task id 0.
+ -1);
+
+ // Make the high priority task an active object.
+ if (this->high_priority_task_->activate
+ (GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 0,
+ this->high_priority_) == -1)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) task activation at priority %d ")
+ ACE_TEXT (" failed, exiting!\n%a"),
+ this->high_priority_,
+ -1));
+
+ ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
+ ready_mon,
+ GLOBALS::instance ()->ready_mtx_,
+ -1));
+
+ // Wait on the condition variable for the high priority client to
+ // finish parsing the arguments.
+
+ while (!GLOBALS::instance ()->ready_)
+ GLOBALS::instance ()->ready_cnd_.wait ();
+
+ // Default return success.
+ return 0;
+}
+
+int
+Server::activate_low_servants (void)
+{
+ if (static_cast<int> (this->num_low_priority_) > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating %d servants starting at priority %d\n",
+ this->num_low_priority_,
+ this->low_priority_));
+
+ // Create the low priority servants.
+ ACE_NEW_RETURN (this->low_priority_tasks_,
+ Cubit_Task *[GLOBALS::instance ()->num_of_objs],
+ -1);
+ }
+
+ // Strip the provided addr from the endpoint and make the ORB
+ // choose the remaining endpoints based on the protocol used in
+ // the endpoint.
+ //
+ // e.g.: orignal endpoint: iiop://foobar:10001
+ // random endpoint iiop://
+
+ const char protocol_delimiter[] = "://";
+
+ char *addr = ACE_OS::strstr (GLOBALS::instance ()->endpoint,
+ protocol_delimiter);
+
+ size_t random_endpoint_length =
+ ACE_OS::strlen (GLOBALS::instance ()->endpoint) -
+ ACE_OS::strlen (addr) +
+ ACE_OS::strlen (protocol_delimiter);
+
+ char random_endpoint[BUFSIZ];
+
+ ACE_OS::sprintf (random_endpoint, "-ORBEndpoint ");
+
+ ACE_OS::strncat (random_endpoint,
+ GLOBALS::instance ()->endpoint,
+ random_endpoint_length);
+
+ for (int i = this->num_low_priority_;
+ i > 0;
+ i--)
+ {
+ char *low_second_argv[] =
+ {random_endpoint,
+ const_cast<char *> ("-ORBSndSock 32768 "),
+ const_cast<char *> ("-ORBRcvSock 32768 "),
+ 0};
+ ACE_NEW_RETURN (this->low_argv_,
+ ACE_ARGV (this->argv_,
+ low_second_argv),
+ -1);
+
+ ACE_NEW_RETURN (this->low_priority_tasks_ [i - 1],
+ Cubit_Task (this->low_argv_->buf (),
+ "internet",
+ 1,
+ &this->servant_manager_,
+ i),
+ -1);
+
+ // Make the low priority task an active object.
+ if (this->low_priority_tasks_[i - 1]->activate
+ (GLOBALS::instance ()->thr_create_flags,
+ 1,
+ 0,
+ this->low_priority_) == -1)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) task activation at priority %d ")
+ ACE_TEXT (" failed, exiting!\n%a"),
+ this->low_priority_,
+ -1));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Created servant %d with priority %d\n",
+ i,
+ this->low_priority_));
+
+ // Use different priorities on thread per rate or multiple
+ // priority.
+ if (GLOBALS::instance ()->use_multiple_priority == 1
+ || GLOBALS::instance ()->thread_per_rate == 1)
+ {
+ this->counter_ = (this->counter_ + 1) % this->grain_;
+
+ if (this->counter_ == 0
+ //Just so when we distribute the priorities among the
+ //threads, we make sure we don't go overboard.
+ && this->num_priorities_ * this->grain_ > this->num_low_priority_ - (i - 1))
+ // Get the next higher priority.
+ this->low_priority_ = ACE_Sched_Params::next_priority
+ (ACE_SCHED_FIFO,
+ this->low_priority_,
+ ACE_SCOPE_THREAD);
+ }
+ } /* end of for() */
+
+ // default return success.
+ return 0;
+}
+
+int
+Server::start_servants (void)
+{
+ // Do the preliminary argument processing for options -p and -h.
+ this->prelim_args_process ();
+
+ // Find the priority for the high priority servant.
+ this->high_priority_ = this->priority_.get_high_priority ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Creating servant 0 with high priority %d\n",
+ this->high_priority_));
+
+ // Activate the high priority servant task
+ if (this->activate_high_servant () < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Failure in activating high priority servant\n"),
+ -1);
+
+ this->num_low_priority_ =
+ GLOBALS::instance ()->num_of_objs - 1;
+
+ // Initialize the priority of the low priority servants.
+ this->init_low_priority ();
+
+ // Activate the low priority servants.
+ if (this->activate_low_servants () < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Failure in activating low priority servant\n"),
+ -1);
+
+ // Wait in the barrier.
+ GLOBALS::instance ()->barrier_->wait ();
+
+ int result = this->write_iors ();
+ if (result != 0)
+ return result;
+ return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int result;
+
+ Server server;
+
+ result = server.init (argc, argv);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in Initialization\n"),
+ 1);
+
+ // run the server.
+ result = server.run ();
+ ACE_DEBUG ((LM_DEBUG,
+ "%s:%d\n", __FILE__, __LINE__));
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error while running the servants\n"),
+ 2);
+ return 0;
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.h b/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.h
new file mode 100644
index 00000000000..1cfd32f967e
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/server.h
@@ -0,0 +1,141 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests
+//
+// = FILENAME
+// server.h
+//
+// = AUTHOR
+// Andy Gokhale, Sumedh Mungee,Sergio Flores-Gaitan and Nagarajan
+// Surendran.
+//
+// ============================================================================
+
+#ifndef SERVER_H
+#define SERVER_H
+
+// ACE includes.
+
+#if defined (TAO_PLATFORM_SVC_CONF_FILE_NOTSUP)
+#define TAO_DEFAULT_SERVER_STRATEGY_FACTORY_ARGS \
+{ "-ORBconcurrency", "thread-per-connection", \
+ "-ORBdemuxstrategy", "dynamic", \
+ "-ORBtablesize", "128" }
+#endif /* TAO_PLATFORM_SVC_CONF_FILE_NOTSUP */
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/ARGV.h"
+#include "ace/Sched_Params.h"
+
+// MT Cubit application includes.
+#include "cubit_i.h"
+#include "Task_Client.h"
+#include "Util_Thread.h"
+#include "Globals.h"
+#include "Cubit_Task.h"
+
+#if defined (VME_DRIVER)
+#include <hostLib.h>
+extern "C" STATUS vmeDrv (void);
+extern "C" STATUS vmeDevCreate (char *);
+#endif /* VME_DRIVER */
+
+class Server
+{
+ // = TITLE
+ // A multithreaded cubit server class.
+ //
+ // = DESCRIPTION
+ // This class encapsulates the functionality of a multi-threaded
+ // cubit server. To use this, call initialize and then
+ // start_servants method.
+public:
+ Server (void);
+ // Default constructor.
+
+ int init (int argc, char **argv);
+ // Initialize the server state.
+
+ int run (void);
+ // Run method.
+
+private:
+ int start_servants (void);
+ // Start the high and low priority servants.
+
+ void prelim_args_process (void);
+ // Preliminary argument processing code.
+
+ void init_low_priority (void);
+ // sets the priority to be used for the low priority servants.
+
+ int write_iors (void);
+ // Writes the iors of the servants to a file
+
+ int activate_high_servant (void);
+ // Activates the high priority servant.
+
+ int activate_low_servants (void);
+ // Activates the low priority servants.
+
+ int argc_;
+ // Number of arguments for the servant.
+
+ char **argv_;
+ // Arguments for the ORB.
+
+ char * *cubits_;
+ // Array to hold pointers to the Cubit objects.
+
+ Cubit_Task *high_priority_task_;
+ // Pointer to the high priority task
+
+ Cubit_Task **low_priority_tasks_;
+ // Array to hold pointers to the low priority tasks.
+
+ ACE_Sched_Priority high_priority_;
+ // Priority used for the high priority servant.
+
+ ACE_Sched_Priority low_priority_;
+ // Priority used by the low priority servants.
+
+ u_int num_low_priority_;
+ // Number of low priority servants
+
+ u_int num_priorities_;
+ // Number of priorities used.
+
+ u_int grain_;
+ // Granularity of the assignment of the priorities. Some OSs have
+ // fewer levels of priorities than we have threads in our test, so
+ // with this mechanism we assign priorities to groups of threads
+ // when there are more threads than priorities.
+
+ u_int counter_;
+ // count of the number of priorities used within a grain.
+
+ ACE_ARGV *high_argv_;
+ // argv passed to the high priority servant.
+
+ ACE_ARGV *low_argv_;
+ // argv passed to the low priority servants.
+
+ MT_Priority priority_;
+ // Priority helper object.
+
+ ACE_Thread_Manager servant_manager_;
+ // Thread manager for the servant threads.
+};
+
+#endif /* SERVER_H */
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/summarize b/TAO/performance-tests/Cubit/TAO/MT_Cubit/summarize
new file mode 100755
index 00000000000..3fb8cf24cc8
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/summarize
@@ -0,0 +1,63 @@
+eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}'
+ & eval 'exec perl -w -S $0 $argv:q'
+ if 0;
+
+# $Id$
+#
+# Summarizes results from a series of runs of MT_Cubit_Test, with
+# different numbers of clients. Example usage:
+#
+# $ for i in 0 1 2 5 10 15 20 25 30 35 40 45 50; do ./MT_Cubit_Test $i; done
+# $ ./summarize
+#
+# The first three lines above let this script run without specifying the
+# full path to perl, as long as it is in the user's PATH.
+# Taken from perlrun man page.
+
+@files = glob 'client-*.log';
+@total_threads = ();
+
+foreach $file (@files) {
+ my ($i);
+ ($i = $file) =~ s/client-(\d+).log/$1/;
+ push @total_threads, $i;
+}
+
+print " Round-trip, usec\n";
+print "Low-priority High-priority Low-priority\n";
+print " threads Latency Jitter Latency Jitter\n";
+
+foreach $total_threads (sort {$a <=> $b} @total_threads) {
+ undef $high_latency;
+ undef $high_jitter;
+ undef $low_latency;
+ undef $low_jitter;
+
+ open (FILE, "client-${total_threads}.log") ||
+ die "$0: unable to open \"client-${total_threads}.log\"\n";
+ while (<FILE>) {
+ #### Add 0.5 to round instead of truncate.
+
+ if (/^High priority client latency : ([\d\.]+) msec, jitter: ([\d\.]+)/) {
+ #### For old versions of client.cpp that printed out in msec.
+ $high_latency = ($1 + 0.5) * 1000;
+ $high_jitter = ($2 + 0.5) * 1000;
+ } elsif (/^High priority client latency : ([\d\.]+) usec, jitter: ([\d\.]+)/) {
+ $high_latency = $1 + 0.5;
+ $high_jitter = $2 + 0.5;
+ } elsif (/^Low priority client latency : ([\d\.]+) msec, jitter: ([\d\.]+)/) {
+ #### For old versions of client.cpp that printed out in msec.
+ $low_latency = ($1 + 0.5) * 1000;
+ $low_jitter = ($2 + 0.5) * 1000;
+ last;
+ } elsif (/^Low priority client latency : ([\d\.]+) usec, jitter: ([\d\.]+)/) {
+ $low_latency = $1 + 0.5;;
+ $low_jitter = $2 + 0.5;;
+ last;
+ }
+ }
+ close FILE;
+
+ printf " %3d %8d %8d %8d %8d\n",
+ $total_threads - 1, $high_latency, $high_jitter, $low_latency, $low_jitter;
+}
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/svc.conf b/TAO/performance-tests/Cubit/TAO/MT_Cubit/svc.conf
new file mode 100644
index 00000000000..bb4034051b9
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/svc.conf
@@ -0,0 +1,8 @@
+# $Id$
+#
+# Please see $TAO_ROOT/docs/Options.html for details on these options.
+#
+
+static Advanced_Resource_Factory "-ORBInputCDRAllocator null -ORBConnectionCacheLock null"
+static Client_Strategy_Factory "-ORBProfileLock null -ORBClientConnectionHandler RW"
+static Server_Strategy_Factory "-ORBConcurrency thread-per-connection -ORBPOALock null -ORBAllowReactivationOfSystemids 0"
diff --git a/TAO/performance-tests/Cubit/TAO/MT_Cubit/svc.conf.xml b/TAO/performance-tests/Cubit/TAO/MT_Cubit/svc.conf.xml
new file mode 100644
index 00000000000..3d76eda6597
--- /dev/null
+++ b/TAO/performance-tests/Cubit/TAO/MT_Cubit/svc.conf.xml
@@ -0,0 +1,11 @@
+<?xml version='1.0'?>
+<!-- Converted from ./performance-tests/Cubit/TAO/MT_Cubit/svc.conf by svcconf-convert.pl -->
+<ACE_Svc_Conf>
+ <!-- $Id$ -->
+ <!-- -->
+ <!-- Please see $TAO_ROOT/docs/Options.html for details on these options. -->
+ <!-- -->
+ <static id="Advanced_Resource_Factory" params="-ORBInputCDRAllocator null -ORBConnectionCacheLock null"/>
+ <static id="Client_Strategy_Factory" params="-ORBProfileLock null -ORBClientConnectionHandler RW"/>
+ <static id="Server_Strategy_Factory" params="-ORBConcurrency thread-per-connection -ORBPOALock null -ORBAllowReactivationOfSystemids 0"/>
+</ACE_Svc_Conf>