summaryrefslogtreecommitdiff
path: root/performance-tests
diff options
context:
space:
mode:
authornanbor <nanbor@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-17 20:48:48 +0000
committernanbor <nanbor@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-17 20:48:48 +0000
commite5f6286a5b00f2cee02c4d6a345e2533e64b4e33 (patch)
tree7167bb1218f942e3d191602ea5161b35e0a16cc4 /performance-tests
parent7a91fa0a3dd9e88385f9137e8b6687e531264e66 (diff)
downloadATCD-e5f6286a5b00f2cee02c4d6a345e2533e64b4e33.tar.gz
*** empty log message ***
Diffstat (limited to 'performance-tests')
-rw-r--r--performance-tests/TCP/Makefile42
-rw-r--r--performance-tests/TCP/tcp_test.cpp652
2 files changed, 694 insertions, 0 deletions
diff --git a/performance-tests/TCP/Makefile b/performance-tests/TCP/Makefile
new file mode 100644
index 00000000000..1dc7f2dc175
--- /dev/null
+++ b/performance-tests/TCP/Makefile
@@ -0,0 +1,42 @@
+#----------------------------------------------------------------------------
+# $Id$
+#
+# Makefile for tests of the miscellaneous ACE performance tests
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+BIN = tcp_test
+LDLIBS = $(MATHLIB)
+
+BUILD = $(VBIN)
+
+# For make depend.
+SRC = $(addsuffix .cpp, $(BIN))
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(ACE_ROOT)/include/makeinclude/macros.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.common.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.local.GNU
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Dependencies
+#----------------------------------------------------------------------------
+
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/performance-tests/TCP/tcp_test.cpp b/performance-tests/TCP/tcp_test.cpp
new file mode 100644
index 00000000000..7a850461dd1
--- /dev/null
+++ b/performance-tests/TCP/tcp_test.cpp
@@ -0,0 +1,652 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// performance-tests/TCP
+//
+// = FILENAME
+// tcp_test.cpp
+//
+// = DESCRIPTION
+// Measures TCP round-trip performance.
+//
+// = AUTHORS
+// Based on udp_test by Fred Kuhns and David L. Levine
+// Modified by Carlos O'Ryan and Nanbor Wang.
+//
+// ============================================================================
+
+#include "ace/Reactor.h"
+#include "ace/Select_Reactor.h"
+#include "ace/TP_Reactor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/ACE.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Stats.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Sched_Params.h"
+#include <math.h>
+
+ACE_RCSID(TCP, tcp_test, "$Id$")
+
+// Global variables (evil).
+static const u_short DEFPORT = 5050;
+static const int MAXPKTSZ = 65536;
+static const int DEFPKTSZ = 64;
+static const int DEFITERATIONS = 1000;
+static const int DEFINTERVAL = 0;
+static const int DEFAULT_THRNO = 10;
+
+static char sbuf[MAXPKTSZ];
+static char rbuf[MAXPKTSZ];
+
+static int usdelay = DEFINTERVAL;
+static int bufsz = DEFPKTSZ;
+static int VERBOSE = 0;
+static int svr_thrno = DEFAULT_THRNO;
+static int server = 0;
+static int client = 0;
+static int nsamples = DEFITERATIONS;
+static int so_bufsz = 0;
+static u_int use_reactor = 0;
+
+enum {
+ SELECT = 1,
+ TP,
+ WFMO
+};
+
+
+static void
+usage (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ "tcp_test\n"
+ " [-v] (Verbose)\n"
+ " [-m message size]\n"
+ " [-i iterations]\n"
+ // " [-I usdelay]\n"
+ " [-b socket bufsz] \n"
+ " [-p port]\n"
+ " [-s]\n"
+ " [-c]\n"
+ // " [-x max_sample_allowed]\n"
+ " [-a to use the ACE Select reactor]\n"
+ " [-x to use the ACE TP reactor]\n"
+ " [-w to use the ACE WFMO reactor]\n"
+ " targethost \n"));
+}
+
+// ****************************************************************
+
+class Client : public ACE_Event_Handler
+{
+public:
+ Client (const ACE_INET_Addr &remote_addr);
+
+ virtual ~Client (void);
+
+ // = Override <ACE_Event_Handler> methods.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ int send (const char *buf, size_t len);
+ // Send the <buf> to the server.
+
+ int get_response (char *buf, size_t len);
+ // Wait for the response.
+
+ int run (void);
+ // Send messages to server and record statistics.
+
+ int shutdown (void);
+ // Send shutdown message to server.
+
+private:
+ ACE_SOCK_Stream endpoint_;
+ // To send messages and receive responses.
+
+ ACE_INET_Addr remote_addr_;
+ // The address to send messages to.
+
+ ACE_UNIMPLEMENTED_FUNC (Client (void))
+ ACE_UNIMPLEMENTED_FUNC (Client (const Client &))
+ ACE_UNIMPLEMENTED_FUNC (Client &operator= (const Client &))
+};
+
+Client::Client (const ACE_INET_Addr &remote_addr)
+ : remote_addr_ (remote_addr)
+{
+ ACE_SOCK_Connector connector;
+ if (connector.connect (this->endpoint_, remote_addr) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "Client - %p\n",
+ "connect failed"));
+ }
+
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "ACE_Reactor::register_handler: Client\n"));
+ }
+}
+
+Client::~Client (void)
+{
+}
+
+ACE_HANDLE
+Client::get_handle (void) const
+{
+ return this->endpoint_.get_handle ();
+}
+
+int
+Client::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ ssize_t n = this->endpoint_.recv (buf, sizeof buf);
+
+ if (n == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "handle_input"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) buf of size %d = %*s\n",
+ n,
+ n,
+ buf));
+
+ return 0;
+}
+
+int
+Client::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ this->endpoint_.close ();
+ return 0;
+}
+
+int
+Client::send (const char *buf, size_t len)
+{
+ return this->endpoint_.send (buf, len);
+}
+
+int
+Client::get_response (char *buf, size_t len)
+{
+ return this->endpoint_.recv (buf, len);
+}
+
+int
+Client::run (void)
+{
+ ACE_OS::memset (sbuf, 0, bufsz);
+ ACE_OS::memset (rbuf, 0, bufsz);
+
+ for (int j = 0; j != 100; ++j)
+ {
+ if (this->send (sbuf, bufsz) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "send"), -1);
+
+ // ssize_t n;
+ if ((this->get_response (rbuf, bufsz)) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "get_response"), -1);
+ }
+
+ ACE_Throughput_Stats throughput;
+
+ ACE_hrtime_t test_start = ACE_OS::gethrtime ();
+ for (int i = 0; i != nsamples; ++i)
+ {
+ ACE_hrtime_t start = ACE_OS::gethrtime ();
+ if (this->send (sbuf, bufsz) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "send"), -1);
+
+ // ssize_t n;
+ if ((this->get_response (rbuf, bufsz)) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "get_response"), -1);
+
+ ACE_hrtime_t end = ACE_OS::gethrtime ();
+
+ throughput.sample (end - test_start,
+ end - start);
+
+ if (VERBOSE && i % 500 == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Send %d / %d events\n", i, nsamples));
+ }
+ }
+
+ ACE_UINT32 gsf = ACE_High_Res_Timer::global_scale_factor ();
+
+ throughput.dump_results ("Client", gsf);
+
+ return 0;
+}
+
+int
+Client::shutdown (void)
+{
+ const char buf = 'S';
+ int n = this->endpoint_.send (&buf, 1u);
+
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::remove_handler: Client\n"),
+ -1);
+ }
+
+ return n;
+}
+
+// ****************************************************************
+
+class Server : public ACE_Event_Handler
+{
+public:
+ Server (const ACE_INET_Addr &addr);
+
+ virtual ~Server (void);
+
+ // = Override <ACE_Event_Handler> methods.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+private:
+ ACE_SOCK_Stream endpoint_;
+ // Receives datagrams.
+
+ ACE_UNIMPLEMENTED_FUNC (Server (void))
+ ACE_UNIMPLEMENTED_FUNC (Server (const Server &))
+ ACE_UNIMPLEMENTED_FUNC (Server &operator= (const Server &))
+};
+
+Server::Server (const ACE_INET_Addr &addr)
+{
+ ACE_SOCK_Acceptor acceptor;
+
+ if (acceptor.open (addr, 1) == -1)
+ ACE_DEBUG ((LM_DEBUG, "%p\n", "open"));
+
+ ACE_DEBUG ((LM_DEBUG, "Listening on %s:%d\n",
+ addr.get_host_name (),
+ addr.get_port_number ()));
+ if (acceptor.accept (this->endpoint_) == -1)
+ ACE_ERROR ((LM_ERROR, "Server::Server %p\n",
+ "accept failed"));
+
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->register_handler
+ (this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "ACE_Reactor::register_handler: Server\n"));
+ }
+
+#if !defined (ACE_LACKS_SOCKET_BUFSIZ)
+ if (so_bufsz != 0)
+ {
+ if (this->endpoint_.set_option (SOL_SOCKET,
+ SO_SNDBUF,
+ (void *) &so_bufsz,
+ sizeof (so_bufsz)) == -1
+ && errno != ENOTSUP)
+ ACE_ERROR ((LM_ERROR, "Server::Server: SO_SNDBUF %p\n",
+ "set_option failed"));
+ else if (this->endpoint_.set_option (SOL_SOCKET,
+ SO_RCVBUF,
+ (void *) &so_bufsz,
+ sizeof (so_bufsz)) == -1
+ && errno != ENOTSUP)
+ ACE_ERROR ((LM_ERROR, "Server::Server: SO_RCVBUF %p\n",
+ "set_option failed"));
+ }
+#endif /* !ACE_LACKS_SOCKET_BUFSIZ */
+ if (acceptor.close () == -1)
+ ACE_ERROR ((LM_ERROR, "Server::Server %p\n",
+ "close failed"));
+}
+
+Server::~Server (void)
+{
+ this->endpoint_.close ();
+}
+
+ACE_HANDLE
+Server::get_handle (void) const
+{
+ return this->endpoint_.get_handle ();
+}
+
+int
+Server::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ ssize_t n = this->endpoint_.recv (buf, sizeof buf);
+
+ if (n == -1)
+ ACE_DEBUG ((LM_ERROR,
+ "%p\n",
+ "handle_input: recv"));
+
+ // Send the message back as the response.
+ if (this->endpoint_.send (buf, n) == n)
+ {
+ if (n == 1 && buf[0] == 'S')
+ {
+ if (!use_reactor)
+ {
+ // Indicate done by returning 1.
+ return 1;
+ }
+
+ if (ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::remove_handler: server\n"),
+ -1);
+
+ ACE_Reactor::end_event_loop ();
+ }
+
+ return 0;
+ }
+
+ ACE_DEBUG ((LM_ERROR,
+ "%p\n",
+ "handle_input: send"));
+ return -1;
+}
+
+int
+Server::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ this->endpoint_.close ();
+
+ return 0;
+}
+
+static void *
+thread_pool_worker (void *)
+{
+ // Server thread function.
+
+ while (!ACE_Reactor::event_loop_done ())
+ {
+ if (ACE_Reactor::instance ()->handle_events () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ASYS_TEXT ("(%t) %p\n"),
+ ASYS_TEXT ("Error handling events")));
+ }
+
+ return 0;
+}
+
+int
+run_server (ACE_INET_Addr &addr)
+{
+ if (use_reactor)
+ {
+ ACE_Reactor *new_reactor = 0;
+
+ switch (use_reactor)
+ {
+ case SELECT:
+ {
+ ACE_Select_Reactor *sr = new ACE_Select_Reactor ();
+ new_reactor = new ACE_Reactor (sr, 1);
+ }
+ break;
+ case TP:
+ {
+ ACE_TP_Reactor *sr = new ACE_TP_Reactor ();
+ new_reactor = new ACE_Reactor (sr, 1);
+ }
+ break;
+ case WFMO:
+#if defined (ACE_WIN32)
+
+#else
+
+#endif /* ACE_WIN32 */
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, "Invalid reactor type selected\n"), -1);
+ }
+ ACE_Reactor::instance (new_reactor, 1);
+ }
+
+ Server server (addr);
+
+ if (!use_reactor)
+ {
+ // Handle input in the current thread.
+ // This is actually equivalent to thread-per-connection model.
+ while (server.handle_input (0) != 1)
+ continue;
+ }
+ else
+ {
+ switch (use_reactor)
+ {
+ case SELECT:
+ // Run the reactor event loop.
+ ACE_Reactor::run_event_loop ();
+ break;
+ case TP:
+ ACE_Thread_Manager::instance ()->spawn_n (svr_thrno,
+ thread_pool_worker);
+ ACE_Thread_Manager::instance ()->wait ();
+ break;
+ case WFMO:
+ break;
+ default:
+ break; // won't happen here.
+ }
+ }
+
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int c, dstport = DEFPORT;
+ int priority =
+ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO)
+ + ACE_Sched_Params::priority_max (ACE_SCHED_FIFO)) / 2;
+ priority = ACE_Sched_Params::next_priority (ACE_SCHED_FIFO,
+ priority);
+ // Enable FIFO scheduling, e.g., RT scheduling class on Solaris.
+
+ if (ACE_OS::sched_params (ACE_Sched_Params (ACE_SCHED_FIFO,
+ priority,
+ ACE_SCOPE_PROCESS)) != 0)
+ {
+ if (ACE_OS::last_error () == EPERM)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "server (%P|%t): user is not superuser, "
+ "test runs in time-shared class\n"));
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ "server (%P|%t): sched_params failed\n"));
+ }
+
+
+ ACE_Get_Opt getopt (argc, argv, "xwf:vb:I:p:sci:m:at:");
+
+ while ((c = getopt ()) != -1)
+ {
+ switch ((char) c)
+ {
+ case 'v':
+ VERBOSE = 1;
+ break;
+
+ case 'm':
+ bufsz = ACE_OS::atoi (getopt.optarg);
+
+ if (bufsz <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nMessage size must be greater than 0!\n\n"),
+ 1);
+
+ case 'i':
+ nsamples = ACE_OS::atoi (getopt.optarg);
+ if (nsamples <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nIterations must be greater than 0!\n\n"),
+ 1);
+ break;
+
+ case 'a':
+ use_reactor = SELECT;
+ break;
+
+ case 'x':
+ use_reactor = TP;
+ break;
+
+ case 'w':
+#if defined (ACE_WIN32)
+ use_reactor = WFMO;
+ break;
+#else
+ ACE_ERROR_RETURN ((LM_ERROR, "WFMO_Reactor is not supported\n"), -1);
+#endif /* ACE_WIN32 */
+
+ case 'b':
+ so_bufsz = ACE_OS::atoi (getopt.optarg);
+
+ if (so_bufsz <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nInvalid socket buffer size!\n\n"),
+ 1);
+ break;
+
+ case 'I':
+ usdelay = ACE_OS::atoi (getopt.optarg);
+
+ if (usdelay < 0)
+ {
+ usdelay = 0;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%s: bad usdelay: %s\n",
+ argv[0],
+ getopt.optarg),
+ 1);
+ }
+ break;
+
+ case 'p':
+ dstport = ACE_OS::atoi (getopt.optarg);
+ if (dstport <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nInvalid port number!\n\n"),
+ 1);
+ break;
+ case 't':
+ svr_thrno = ACE_OS::atoi (getopt.optarg);
+
+ if (svr_thrno <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nInvalid server thread number!\n\n"),
+ 1);
+ break;
+
+ case 'c':
+ server = 0;
+ client = 1;
+ break;
+ case 's':
+ client = 0;
+ server = 1;
+ break;
+ default:
+ usage ();
+ return 1;
+ }
+ }
+
+ if (getopt.optind >= argc && client || argc == 1)
+ {
+ usage ();
+ return 1;
+ }
+
+ ACE_INET_Addr addr (dstport);
+
+ if (server)
+ return run_server (addr);
+
+ if ((u_int) bufsz < sizeof (ACE_hrtime_t))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nbufsz must be >= %d\n",
+ sizeof (ACE_hrtime_t)),
+ 1);
+
+ ACE_INET_Addr remote_addr;
+
+ if (isdigit(argv[getopt.optind][0]))
+ {
+ if (remote_addr.set (dstport,
+ (ACE_UINT32) ACE_OS::inet_addr
+ (argv[getopt.optind])) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "invalid IP address: %s\n",
+ argv[getopt.optind]),
+ 1);
+ }
+ else
+ {
+ if (remote_addr.set (dstport, argv[getopt.optind]) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "invalid IP address: %s\n",
+ argv[getopt.optind]),
+ 1);
+ }
+ getopt.optind++;
+
+ ACE_DEBUG ((LM_DEBUG, "Connecting to %s:%d\n",
+ remote_addr.get_host_name (),
+ remote_addr.get_port_number ()));
+
+ Client client (remote_addr);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nSending %d byte packets to %s:%d "
+ "with so_bufsz = %d\n\n",
+ bufsz,
+ addr.get_host_name (),
+ dstport,
+ so_bufsz));
+
+ client.run ();
+ client.shutdown ();
+
+ return 0;
+}