|
A facility is normally
used to model a resource (something a
process requests service from) in a simulated
system. For example, in a model of a computer
system, a CPU and a disk drive might both
be modeled by CSIM facilities. A simple
facility consists of a single server and
a single queue (for processes waiting
to gain access to the server). Only one
process at a time can be using a server.
A multiserver-server facility contains
a single queue and multiple servers. All
of the waiting processes are placed in
the queue until one of the servers becomes
available. A facility set is an array
of simple facilities; in essence, a facility
set consists of multiple single server
facilities, each with its own queue.
Normally, processes
are ordered in a facility queue by their
priority (a higher priority process is
ahead of a lower priority process). In
cases of ties in priorities, the order
is first-come, first-served (fcfs). An
fcfs facility can be designated as a synchronous
facility. Each synchronous facility has
its own clock with a period and a phase
and all reserve operations are delayed
until the onset of the next clock cycle.
Service disciplines other than priority
order can be established for a server.
These are described in section
4.11, "Changing the Service Discipline
at a Facility".
A set of usage and queueing
statistics is automatically maintained
for each facility in a model. The statistics
for all facilities which have been used
are "printed" when either a
report (see section
19.2, "CSIM Report Output")
or a report_facilities is executed
(see section 4.4,
"Producing Reports" for details
about the reports that are generated).
In addition, there is a set of inspector
methods that can be used to extract individual
statistics for each facility.
First time users of
facilities should focus on the following
four sections, which explain how to set
up facilities, use (and reserve and release)
facilities, and produce reports. Subsequent
sections describe the more advanced features
of facilities.
A dynamic facility pointer
is declared:
Dynamic Example:
facility *fd
Before a dynamic facility
can be used, it must be initialized by
invoking the facility constructor
by calling new:
Prototype: facility::facility(char
*name)
Static Example: facility
fs("fac")
Dynamic Example: fd
= new facility("fac");
A newly created facility
is created with a single server which
is "free". The facility name
is used only to identify the facility
in output reports and trace messages.
Facilities should be
declared with global pointers and constructed
in the first process (normally the process
named sim) prior to the beginning
of the simulation part of the model. Unless
changed by a set_servicefunc method
(see section
4.11, "Changing the Service Disciplines
at a Facility"), the scheduling policy
of the facility will be first-come, first-served
(fcfs).
A process typically
uses a server for a specified interval
of time.
Prototype: void
facility::use(double);
Dynamic Example:
fd ->use(exponential(1.0));
If the server at this
facility is free (not being used by another
process), then the process gains exclusive
use of the server and the usage interval
starts immediately. At the end of the
usage interval, the process gives up use
of the server and departs this facility.
Execution continues at the statement following
the use statement.
If the server at this
facility is busy (is being used by another
process), then the newly arriving process
is placed in a queue of waiting processes;
this queue is ordered by process priority,
with processes of equal priority being
ordered by time of arrival. As each process
completes its usage interval, the process
at the head of the queue is assigned to
the server and its usage interval starts
at that time.
The service discipline
at a facility specifies how processes
are given access to the server. One of
several different service disciplines
can be specified for a facility. Also,
another form of facility has multiple
servers. In addition, it is possible to
have an array of facilities (a facility
set). The difference between a multiserver
facility and a facility set is that a
multiserver facility has one queue for
all of the waiting processes, while a
facility set has a separate queue for
each facility in the set.
In some cases, a process
will acquire a server, but will do something
other than enter the usage interval when
it gets the server. The statements for
doing this are reserve (to gain
exclusive use of a server) and release
(to relinquish use of the server acquired
in a previous reserve statement)
Prototypes: long
facility::reserve(void);
void facility::release(void);
Dynamic Examples: fd->reserve();
fd->release();
When a process executes
a reserve, it either gets use of
the server immediately (if the server
is not busy) or it is suspended and placed
in a queue of processes waiting to get
use of the server. When it gains access
to the server, it executes the statement
following the reserve statement.
The order of processes in the queue is
by process priority, with processes of
equal priority being ordered by time of
arrival. This process priority service
discipline is called fcfs in CSIM; it
(along with fcfs_sy, see below)
is the only service discipline that can
be specified for facilities where processes
do this reserve-release style of
access. If another service discipline
is in force, then the processes must execute
use statements instead of reserve-release
pairs of statements.
The process releasing
a server at a facility must be the same
process as the one which reserved it.
If this is not the case, then the release_server
statement (see below) must be used. When
a process executes a release, it gives
up use of the server; if there is at least
one process waiting to start using the
server (i.e., there is at least
one process in the queue at this facility),
the process at the head of the queue is
given access to the server and that process
is then reactivated and will proceed by
executing the statement following its
reserve statement. No simulation time
passes during execution of a release statement.
Note: Executing
the sequence "f ->reserve(); hold(t);f
->release();" is equivalent to
executing the statement "f ->use(t)'"
However, if the usage interval is specified
by a random number function, then there
is a subtle difference between these,
as follows: the randomly derived interval
is determined after gaining access to
the server in the first sequence and before
gaining access to the server with the
use form; thus it is likely that the intervals
in these two examples will be different.
In other words, the sequence "f ->reserve();
hold(exponential(t); f->release();"
will not necessarily display exactly the
same behavior as executing the statement
"f->use(exponential(t));"
Reports for facilities
are most often produced by calling the
report function which prints reports
of all the CSIM objects. Reports can be
produced for all existing facilities by
calling the report method.
Prototype: void
facility_report(void);
Example: facility_report();
The report for the set of facilities,
as illustrated below, includes, for each
facility, the name of the facility, the
service discipline, the average service
time, the utilization, the throughput
rate, the average queue length, the average
response time and the number of completed
service requests.
In some cases, it is
necessary to reset the statistics counters
for a specific facility.
Prototype: void
facility::reset(void)
Example: f->reset();
Executing this statement
does not affect the state of the facility
or its servers. The reset()and the reset_facilities
statements each call facility::reset()
for all facilities in the model.
Sometimes, it is necessary
for one process to reserve a facility
and then for another process to release
the server obtained by the first process.
In this case, the first process has to
save the index of the server it obtained,
and then give this server index to the
second process, so that it can specify
that index in the release_server
statement, as follows:
Dynamic Example:
server_index
= fd->reserve();
Prototype: void
facility::release_server (long
server_index)
Dynamic Example: fd->release_server(server_index);
This operates
in the same way as the release
statement except that the ownership of
the server is not checked; thus, a process
which did not reserve the facility may
release it by executing the release_server
statement
with a server index.
In some cases, a facility
has multiple servers, and each of these
servers is indistinguishable from the
other servers. A pointer to a mutliserver
facility is declared :
Dynamic Example:
facility_ms
*cpud;
A multiserver facility
is constructed:
Prototype:
facility_ms::facility_ms(char
*name,
long ns);
Static
Example:
facility_ms cpus("dual cpu",
2);
Dynamic
Example:
cpud = new
facility_ms("dual cpu", 2);
A process can
either execute a use
statement or the reserve-release
pair of statements at a multiserver facility.
In either case, the process gains access
to any server that is free; a process
is suspended and put in the single queue
at the facility only when all of the servers
are busy.
A facility set is an
array of facilities. A facility set is
initialized as follows:
Prototype:
facility_set::facility_set(char
*name,
long nm_facs);
Static
Example:
facility_set
disks("disks", 10);
Dynamic
Example:
facility_set
*diskd;
diskd =
new facility_set("disk",10);
In a facility set, each
element of the set is an independent,
single server facility, with its own queue.
Each of these facilities is given a constructed
name which shows its position in the set.
In the above example, the name for the
first element of the set is "disk[0]".
Facility sets are used to model cases
where each server has its own queue of
waiting processes.
An individual element
of a facility is accessed as an array
element. In C++ this is non-obvious.
Static Example:
disks[i].use(exponential(1.0));
Dynamic
Example:
(*diskd)[i].use(exponential(1.0));
4.9 Reserving a Facility with a Time-out
Sometimes a process
must not wait indefinitely to gain access
to a server. If a process executes the
timed_reserve
function,
it will be suspended until either it gains
use of a server or the specified time-out
interval expires.
Prototype:
long facility::timed_reserve(double
timeout)
Dynamic
Example:
result =
fd->timed_reserve (100.0);
if (result ! = TIMED_OUT) . . .
The process must check
the functional value, to determine whether
or not it obtained a server. If the value
TIMED_OUT is returned, the process did
not obtain a server. If this is not returned
(EVENT_OCCURRED will in fact be returned),
then the process did obtain a server and
should eventually release the server.
The name of a facility
can be changed at any time, as follows:
Prototype:
void facility::set_name(char
*new_name);
Dynamic
Example:
fd->set_name("cpu");
Only the first ten characters
of the facility's name are stored.
The service discipline
for a facility determines the order in
which processes at the facility are given
access to that facility. If not otherwise
specified, the service discipline for
a facility is fcfs. When the priorities
differ, processes gain access to the server
in priority order (higher priority processes
before lower priority processes). When
processes have the same priority, the
processes gain access in the order of
their arrival at the facility (first come,
first served). This default service discipline
can be changed.
Prototype:
void facility::set_servicefunc(void
(*service_func)())
Dynamic
Example:
fd->servicefunc(pre_res);
Set_servicefunc()
refers to a service function which is
invoked when the use method (described
above) references this facility. This
service function can be any of the following
pre-defined service discipline functions:
- fcfs
- first come, first served
This is the default service discipline
and is described in the introduction
to this section. If the synchronous_facility
statement (see below) is used for this
facility, this will behave like a fcfs_sy
(clock synchronized fcfs) facility.
In other words, there are two ways for
a facility to become synchronized: specifying
the service discipline of fcfs_sy or
specifying (or defaulting) fcfs for
the service discipline and using the
synchronous method
- fcfs_sy
- first come, first served, clock synchronized
This is the same as fcfs except that
requests can be satisfied only at the
beginning of a clock cycle. If not otherwise
specified (via synchronous below), the
clock phase (time to onset of first
clock cycle) will be 0.0, and the period
(length of a clock cycle) will be 1.0.
- inf_srv
- infinite servers
There is no queueing delay at all since
there is always a server available at
the facility.
- lcfs_pr
- last come, first served, preempt
Arriving processes are always serviced
immediately, preempting a process that
is currently being served if necessary.
Priority is not a consideration with
this service discipline.
- prc_shr
- processor sharing
This is load-dependent processor sharing.
Service times for each process are determined
based on the number of processes at
the facility. If not otherwise specified
(see set_loaddep below), it will be
assumed that the rate that applies when
there are n processes at the facility
is n (in other words, if there are n
processes at the facility, the service
time will be multiplied by n). The altered
service times are recomputed as tasks
that arrive at and leave the facility.
There is no queueing delay with processor
sharing since the assumption is that
the server works faster and faster as
necessary to service all processes that
request it.
There can be a maximum of 100 processes
sharing a prc_shr facility.
- pre_res
- preempt resume
Higher priority processes will preempt
lower priority processes, so that the
highest priority process at the facility
will always finish using it first. Where
the priorities are the same, processes
will be served on a first come, first
served basis. Preempted processes will
eventually resume and complete their
service time interval.
- pre_rst
- preempt-restart
Higher priority processes will preempt
lower priority processes, so that the
highest priority process at the facility
will always finish using it first. Where
the priorities are the same, processes
will be served on a first come, first
served basis. Preempted processes will
eventually resume and will restart their
respective service time intervals each
time they resume.
- rnd_pri
- round robin with priority
Higher priority processes will be served
first. When there are multiple processes
with the same priority, they will be
serviced on a round robin basis, with
each getting the amount of time specified
in set_timeslice (see below) before
being preempted by the next process
of the same priority.
- rnd_rob
- round robin
Processes will be serviced on a round
robin basis, with each getting the amount
of time specified in set_timeslice (see
below) before being preempted by the
next process requiring service. Process
priority is not a consideration with
this service discipline.
Caution:
The use
statement (as opposed to the reserve)
statement must be used for most of these
service disciplines to be effective. Only
fcfs and fcfs_sy
will operate properly with reserve.
To set the clock
information for the fcfs_sy
service discipline:
Prototype:
void facility::synchronous(double
phase,double period)
Dynamic
Example:
fd->synchronous
(0.0, 1.0);
To set the load
dependent service rate for the prc_shr
(see above) service discipline:
Prototype:
void facility::set_loaddep(double
rate[], long n)
Dynamic
Example:
fd->set_loaddep(rate, 10);
The "rate"
array is an array of length n,
where each element specifies the service
rate for the corresponding number of processes
using the server. Rate[i]
is the amount by which the service time
is multiplied when there are i
processes at the facility. If n
is less than the 100 (the maximum number
of processes allowed to share use of a
prc_shr
facility),
then the value of the last specified rate
is replicated until 100 values are available.
Also, if n
is greater than 99, only 100 values will
be used. It should be remembered that
the altered service times are recomputed
as tasks arrive at and leave the facility.
To set the time
slice for the round robin service disciplines,
rnd_pri and
rnd_rob
(see above):
Prototype:
void facility::set_timeslice(double
slice_length)
Dynamic
Example:
fd->set_timeslice(0.01);
To delete a dynamic
facility:
Example:
delete fd;
To delete a dynamic
facility set:
Example:
delete f_set;
Caution:
Deleting a facility or facility set is
an extreme action and should be done only
when necessary.
Information about usage
of a facility by processes belonging to
different process classes can be collected
for all facilities or for a specific facility.
To collect class-based usage information
for a specific facility:
Prototype:
void facility::collect_class
Dynamic
Example:
fd->collect_class();
Usage of this facility
by all process classes (see section 17,
"Process Classes") will be reported
in the facilities report. Also, it is
an error to change the maximum number
of classes allowed after this statement
has been executed.
To collect usage information
for all facilities:
Prototype:
void collect_class_facility_all(void)
Example:
collect_class_facility_all();
This applies to all
of the facilities in existence when this
statement is executed Usage of the facilities
by all process classes (see section 17,
"Process Classes" ) will be
reported in the facilities report. It
is an error to change the maximum number
of classes allowed after this statement
has been executed.
All statistics and information
maintained by a facility can be retrieved
during execution of a model or upon its
completion.
| Prototype: |
Functional
Value: |
| char *facility::name() |
pointer to name
of facility |
| long facility::num_servers() |
number of servers
at facility |
| char *facility::service_disp() |
pointer to name
of service discipline at facility |
| double facility::timeslice() |
time in each time-slice
for facility (which has a round robin
service discipline) |
| long facility::num_busy() |
number of servers
currently busy at facility |
| long facility::qlength() |
number of processes
currently
waiting at facility |
| long facility::status() |
current status
of facility
BUSY if all servers are in use
FREE if at least one server is not
in use |
| long facility::completions() |
number of completions
at facility |
| long facility::preempts() |
number of
preempted requests at facility
|
| double facility::qlen() |
mean queue length
at facility |
| double facility::resp() |
mean response time
at facility |
| double facility::serv() |
mean service time
at facility |
| double facility::tput() |
mean throughput
rate at facility |
| double facility::util() |
utilization (%
of time busy) at facility |
Additional
data on servers and classes can be obtained
as follows:
long facility::server_completions(long
sn)
number of completions for server sn at
facility
double facility::server_serv(long
sn)
mean service time for server sn at facility
double facility::server_tput(long
sn)
mean throughput rate for server sn at
facility
double facility::server_util(long
sn)
utilization for server sn at facility
long facility::class_qlength(CLASS
c)
number of process from class at facility
long facility::class_completions(CLASS
c)
number of completions for class at facility
double facility::class_qlen(CLASS
c)
mean queue length for class at facility
double facility::class_resp(CLASS
c)
mean response time for class at facility
double facility::class_serv(CLASS
c)
mean service time for class at facility
double facility::class_tput(CLASS
c)
mean throughput rate for class at facility
double facility::class_util(CLASS
c)
utilization for class at facility
To obtain a report
on the status of all of the facilities
in a model:
Prototype:
void status_facilities
(void)
Example:
status_facilities
();
This report lists
each facility along with the number of
servers, the number of servers which are
busy, the number of processes waiting.
the name and id of each process at a server,
and the name and id of each process in
the queue.
Next
Section
|