CPU runnable_request --------------> disk_activity_requestwith a probability of 1.0 and some duration, possibly greater than 1, to represent a brief period of program execution generating a disk read or write.
Note that when this reaction executes, the CPU count will be reduced by one for the duration of the executing state and when the CPU count appears in a graph you can tell when the CPU is busy.
title: User preparing to respond. reactants: prompt catalysts: user products: user_request probabilities: 1.0 duration: 100 # The next two reactions express the fact that the image may already be in memory. title: Network processes request from user. reactants:user_request, catalysts: server_NIC products: IO_disk_activity_request probabilities: 1.0 duration: 2 title: Network processes request from user. reactants:user_request, catalysts: server_NIC products: runnable_request probabilities: 1.0 duration: 2 # The next three reactions express CPU use options. title: Relinquish a time slice...probability determines average duration of slice. reactants: runnable_request catalysts: CPU products: runnable_request probabilities: .9 duration: 10 title: Request IO_disk activity...probability determines frequency of disk requests. reactants: runnable_request catalysts: CPU products: IO_disk_activity_request probabilities: .01 duration: 1 title: Finish processing request by issuing new prompt and giving up CPU. # This probability determines mean amount of last slice. reactants: runnable_request catalysts: CPU products: ready_to_issue_prompt probabilities: .09 duration: 10 title: Wait in I/O controller queue. reactants: IO_disk_activity_request catalysts: IO_controller products: disk_activity_request probabilities: 1.0 duration: 1 title: Start disk activity. reactants: disk_activity_request catalysts: disk_controller products: disk_activity_finished probabilities: 1.0 duration: 50 title: Complete IO controller activity. reactants: disk_activity_finished catalysts: IO_controller products: runnable_request probabilities: 1.0 duration: 1 title: Wait in I/O controller queue. reactants: ready_to_issue_prompt, catalysts: IO_controller products: server_NIC_activity_request probabilities: 1.0 duration: 1 title: Start net transmission activity. reactants: server_NIC_activity_request catalysts: server_NIC products: prompt probabilities: 1.0 duration: 1Here is an example "molecules" file that can be used with the "reaction set" above:
user = 1 # there must be exactly 1 user per prompt, so see below.... prompt = 1 # the total number of prompts must be the same as num of users. server_NIC = 2 IO_controller = 5 CPU = 3 disk_controller = 8Here is a graph of some of the output variable counts produced using the two files above, and without allowing exponential variation in transition durations:
Molecules | Molecule count with respect to time step |
CPU IO_controller disk_controller prompt user |
For example, CPU use is reflected by the red line with a beginning value of 3. Periods of CPU use are represented by a drop in the count of available (free) CPUs. You can see the time slices utilized by active processes as relatively ragged sections of this line. Clearly, this example shows relatively light disk use when compared with CPU use.
Note that this kind of run helps debug the reaction set, and would usually be rerun with different parameters, particulary with more users defined in the input "molecules" file, and with transition durations allowed to vary according to an exponential distribution.
Here are some results from a run with 10 users, but without variation in durations. Note that "prompts" are introduced into the system one-by-one separated by 9 time steps in this example. If transition durations werea allowed to vary, this artifice would not be necessary.
Molecules | Molecule count with respect to time step |
CPU IO_controller disk_controller prompt user |
The simple approach used above cannot indicate system state or "instrument" the simulation very clearly. In the next model, the state of an object is represented as an object. For example, an available CPU is represented as the object "ready_CPU". When that CPU begins to run a process, one "ready_CPU" disappears and is replaced by one "CPU_running_request".
Also, this model assigns probabilities to achieve distributions of reaction durations. For example, the transition from "ready_CPU" to "CPU_running_request" states happens with a probability of 1.0 so that any available CPU must be used. However, the transition from "CPU_running_request" back to "ready_CPU" state occurs with some smaller probability, so as to represent a time step of variable size used by the request.
title: User preparing to respond. reactants:thinking_user products: user_request_to_network,waiting_user probabilities: .1 duration: 1 title: Network processes request from user. reactants:user_request_to_network,ready_server_NIC products: busy_server_NIC probabilities: .7 duration: 1 title: Network completes request from user. reactants:busy_server_NIC products: user_request_ready_for_IO_controller,ready_server_NIC probabilities: 1.0 duration: 1 title: IO controller processes request. reactants: user_request_ready_for_IO_controller,ready_IO_controller products: IO_controller_reading_user_request_from_NIC probabilities: 1.0 duration: 1 title: IO controller completes request. reactants: IO_controller_reading_user_request_from_NIC products: user_request_ready_for_processing,ready_IO_controller probabilities: 1.0 duration: 1 title: Request that the program image be loaded into memory, if necessary. reactants: user_request_ready_for_processing,ready_CPU products: IO_disk_activity_request, ready_CPU probabilities: 1.0 duration: 1 # whichever gets tried first runs. title: OR, if it is already in memory, just make it runnable. reactants: user_request_ready_for_processing products: runnable_request probabilities:1.0 # whichever gets tried first runs. title: Take a time slice. reactants: runnable_request,ready_CPU products: CPU_running_request probabilities: 1.0 duration: 1 title: Relinquish a time slice...probability determines average duration of slice. reactants: CPU_running_request products: runnable_request,ready_CPU probabilities: .1 duration: 1 title: Request IO_disk activity...probability determines frequency of disk requests. reactants: CPU_running_request products: ready_CPU,IO_disk_activity_request probabilities: .001 duration: 1 title: Finish processing request by issuing new prompt and giving up CPU. # This probability determines mean amount of CPU devoted to request. reactants: CPU_running_request products: ready_CPU,IO_NIC_activity_request probabilities: .1 duration: 1 title: Wait in I/O controller queue. reactants: IO_disk_activity_request,ready_IO_controller products:IO_controller_busy,disk_activity_request probabilities: 1.0 duration: 1 title: Start disk activity. reactants: disk_activity_request,ready_disk_controller,IO_controller_busy products: disk_controller_busy,ready_IO_controller probabilities: 1.0 duration: 1 title: Complete disk activity...prob determines duration of disk activity. reactants: disk_controller_busy products: disk_activity_finished,ready_disk_controller probabilities: .01 duration: 1 title: Complete IO controller activity. reactants: disk_activity_finished,ready_IO_controller products: IO_disk_activity_finished,IO_controller_busy probabilities: 1.0 duration: 1 title: Complete IO_disk activity. reactants: IO_disk_activity_finished,IO_controller_busy products: runnable_request,ready_IO_controller probabilities: 1.0 duration: 1 title: Wait in I/O controller queue. reactants: IO_NIC_activity_request,ready_IO_controller products: server_NIC_activity_request,IO_controller_busy probabilities: 1.0 duration: 1 title: Start net transmission activity. reactants: server_NIC_activity_request,ready_server_NIC,IO_controller_busy products: server_NIC_busy,ready_IO_controller probabilities: 1.0 duration: 1 title: Complete net transmission activity...prob determines amount of net time required. reactants: server_NIC_busy,waiting_user products: server_NIC_activity_finished,ready_server_NIC,thinking_user probabilities:.7 duration: 1 title: Complete IO controller-NIC activity. reactants: server_NIC_activity_finished,ready_IO_controller products: IO_NIC_activity_finished,IO_controller_busy probabilities: 1.0 duration: 1 title: Complete IO_NIC activity. reactants: IO_NIC_activity_finished,IO_controller_busy products: ready_IO_controller probabilities: 1.0 duration: 1Note that time scaling is difficult with this kind of modelling, and choice of probabilities is tricky, but here are some results to demonstrate the usefulness of this approach. This run shows a simulation running with 10 users (still without transition duration variation)..
Molecules | Molecule count with respect to time step |
CPU_running_request IO_controller_busy disk_controller_busy |
It is interesting to note that variable counts in these simulations do not show exponential distributions when examined using Detrended Fluctuation Analysis. The number of available disk controllers, for example, showed distributions similar to power-law (DFA slope of .95), with fixed durations, and runnable_requests showed a distribution somewhere between power-law and random walk (DFA slope of 1.29), when transition durations were exponentially distributed. To the naked eye, runnable_requests showed a distribution not unlike log-normal.
Michael Grobe
December 2003