CS 5523 Operating Systems
Laboratory 3 - Spring 2002
Comparing Threaded Servers
Objectives:
- Understand the worker-pool model.
- Understand the thread-per-connection model.
- Learn about threaded servers.
- Use thread synchronization in a real problem.
- Make meaningful performance measurements and organize them
into graphics and tables.
- Think about experimental design and hypotheses.
Overview:
In this laboratory you will write two versions
of a threaded
server (thread-per-connection and worker-pool) and
compare their performance. In both cases the communication
will be based on TCP.
Requirements:
- You will be writing two versions of the server
(Server Version I and Server Version II) and a client for testing both
servers.
- Your source code must be clean and clear. (It will be read, and you will
be graded on its quality as well as whether the code works.)
- This project must be done in C.
- You must hand in ALL source for each program separately.
- You must hand in the output files for each part separately.
- You must hand in copies of the lint output for each program separately.
It should not contain an indication of any errors.
- You must hand in a word-processed report of 3 to 5 pages summarizing
the structure of your program, known bugs, how you tested the program, and
answers to the questions posed in the assignment. Your report should also
an introductory paragraph and a
diagram of the architectural models implemented in this assignment.
Server version I (thread-per-connection):
Server version I (main thread) listens for a TCP connection request on a well-known
port. After accepting the request, the server creates a
thread to handle the request and resumes listening for another request.
The thread function takes the communication file descriptor as a
parameter. The thread detaches itself, performs the request, closes
the communication file descriptor and exits (by calling
pthread_exit).
Server version I takes
the well-known port
as a command line argument.
Server version II (worker pool with bounded buffer):
Server version II is based
on a producer/consumer model with the main thread being the producer
and the worker threads being consumers.
In the initialization phase, the main thread creates a specified
number of worker threads and a circular buffer of int
of a specified size.
The main thread listens for TCP connection requests on a well-known
port. Each time it accepts a connection, the main thread places the
communication file descriptor that is returned
from accept in a circular buffer and resumes listing
for another connection.
Each worker thread waits for
items (the communication file descriptor values) to become
available in the circular buffer, removes an item, processes
the client request corresponding to that file descriptor,
and closes the communication file descriptor. The worker thread
then resumes waiting for
another item to become available.
Server version II takes the well-known port,
the size of the
buffer, and the size of the
worker-pool as command line arguments.
Client driver:
You should also write a client driver program that takes
the following command line arguments: the hostname of the server,
the port name of the server,
the number of processes to fork, the number of connections per process,
the size of the message body,
and the number of messages per connection.
The client driver will fork the specified number of processes, each
of which will do the following the number of times specified
by connections per process:
- connect to the specified server.
- for the number of messages per connection:
- send the message
- read the response
- calculate and output statistics
- close the connection
Note, the connection request may fail and have to be retried
when the server is busy, so you will need to put this in its
own loop. The number of connections means the number of successful
connections.
The process should get the time before it tries to make a
connection and after it makes the connection. It should also
read the time after it has received the response. It should
write the time differences between these three points to
standard error, along with its PID so that the interleaved
messages from the different processes can be distinguished.
Before each client process exits it should print the
the total number of connection retries it experienced and other
relevant statistics
The message:
Each message from the client should consist of a header
that contains
five long integers in network byte order:
- Process ID of client process
- Client message number
- Length of the message body
- 0
- 0
The header is followed by the message body of the specified length.
Each time the client process sends a message, it increments the
client message number. The client does not reset the message counter
when it makes a new connection.
The response consists of a structure containing the following
long integers in network byte order:
- Process ID of client process
- Client message number
- Length of message body
- Thread ID of thread that processes the message
- Thread message number
Each time a server thread processes a message, it increments
its thread message number. It does not ever reset the message
number to zero.
Gathering statistics:
You should gather statistics about average and median connection times
and response times for the two different servers. For the worker pool you
should compare results for 1, 5, 10 and 50 threads in the pool.
You should vary the number of client processes and also test with
the client driver running simultaneously on multiple machines. You should organize
your results in tables and graphically and draw conclusions about the measurements
in your report.
Questions:
- Under what circumstances
should Server version I exit?
- What happens in Server version I if the main thread
closes the file descriptor after creating a thread to handle
the communication?
- Under what circumstances
should Server version II exit?
- What are the sources of overhead the Server version I implementation?
- What are the sources of overhead the Server version II implementation?
- What is the effect of the start-up phase of the client driver?
- What is the effect of the client message body size on the results?
- In what ways are the resource usage of these two versions of the server different
from those of a real threaded web server?
Project notes:
- This is not a project about TCP and network primitives, but
about server threading. You should use a prewritten library to do your
network communication, rather than fussing with trying to do your own.
If you wish, you may use the new UICI library that will appear in Practical
Unix Programming, 2nd Edition. To get started, download the following files
into a directory and make them. You can then run the client on one machine
and the server on another. The code can then be used as the starting
point for your servers.
This version of UICI is not completely thread safe. The problems come
in with the calls for determining the host name. If you follow the specification,
your program should not encounter any circumstances in which these calls
will be executed at the same time.
- To use the pthreads functions, you must include
pthread.h.
You must also compile with pthread library (-lpthread-mt option if you are using cc.
- Please don't run big timing tests between 8 am in the morning and 6 pm
at night during the week.
- I have given threaded server problems to previous classes (not the same
one) and have done a post-mortem analysis
of the mistakes. You should read
over the post-mortem and make sure that you understand why the problems pointed
out might be problems. You are welcome to ask questions about these in class.
Last Revision: April 7, 2002 at 4:45 am by Kay A. Robbins.
This material may be used for educational purposes provided that the source
is credited.