In
the highly complex and interconnected contemporary world, computers
and humans interact continuously. We need a modelling approach which
can shed light on the similarities between different players of this
interaction rather than sub-divide this interconnected world into
artificially specialist domains.
Cybernetics: the science of communication and automatic
control systems in both machines and living things.
New Oxford
Dictionary Of English
If I was to loose my legs my work would be much less impacted than
if I lost my computer (ignoring the relative ease of replacing
either). The complex interactions we all (in the rich world) now have
with computers leads me to state that study of most computer systems
is now in the realm of cybernetics.
This observation leads to another, more startling one: even the
very simplest of computer programs must be modelled in the context of
a complex system. That system not only being the program but the use
to which the program is put and the way in which other programs and
humans interact with it.
This complexity can seem overwhelming when handled with the
classical analytic tools of mathematics and computer science. We are
still deeply embedded in an approach based on state equilibrium with
an eye to that which is deterministically provable. In contrast, once
computers start to interact with the 'outside world' the a-priory
nature of their programs is contaminated by the messy,
unpredictability of every day life. As a consequence one might feel
that modelling such systems is futile.
All is not lost! We can take a step back and ask ourselves what we
really want to illuminate with our models and what the end result of
our modelling should be. By so doing it might be (and I believe it
is) possible to find a totally different approach which behaves more
unmanageably when faced with this complexity. I shall now indulge in
some simple linguistics to try and dig out what we as humans
generally want from our model:
"When I press this key I want
the computer to just do the right thing."
"Pressing the break pedal
should cause the breaks to engage."
"The wheel lock sensor
detecting a potential skid should activate the ABS system."
"It should let me know when
it has finished."
"The spinning hour glass tells us that it is still
working."
What we can see in each of these are events. We want the
cybernetic system to respond to an event and we detect what has done
through our own sensory experience of events. We can even see this in
terms of the last "hour glass" example: the glass turns to
inform us that a different event (the program crashing) has not
occurred. We are supremely uninterested that the program is working;
we are only interested in events which mark it as having finishing or
having crashed.
Let us consider these ideas in a different way. We are often
taught, and the concept permeates our conversational culture, that
the physical world tends to equilibrium. This notion is embodied in
the natural sciences with such core teaching as Le Chatelier's
Principle. In general, we are urged to seek to understand the
equilibrium state to which a system "wants" to move.
Indeed, we imbue systems with a teleos of stability seeking. However,
we see no equilibria in natural systems. Only by extreme artificial
methods can we impose equilibrium for the briefest of time. Organisms
are created, age and die. Coast lines grow in one area whilst eroding
in another. Even the orbit of our planet shifts on a minute by minute
bases whilst its rotation gradually diminishes. We humans are not
actually interested in basins of temporally delimited
pseudo-equilibria; we are interested in points of measurable change;
we seek the point of boundary crossing; We view the physical world as
the consequence of events which change it not the other way around.
Given all of these observations we can now start to view all of
cybernetics with light of events. Where once we might have used many
disparate concepts to illuminate the field we can now use one and by
so doing unify our view.
Before I go much further discussing the details of this approach,
I must define what I call the 'irreducible anatomy' of the event
model I am proposing. This being the structure of the model expressed
in such a way that any attempt to further reduce its complexity
simply rearranges its complements or alter their names. In other
words, more complexity would be excessive and less would be
insufficient whilst any alternative anatomy might be equally valid
but ultimately will prove to be topologically equivalent (as, for
example, a tea cup is to a torus).
The irreducible anatomy of an event based model
A diagrammatic
representation of the irreducible anatomy of an event based model.
Event sources: are entities which instigate the
marshalling of Event Objects
An event source could be a hardware related activity (e.g. a key
press) or some purely software related thing like a memory state
change.
Marshalling: is the gathering together of a
full description of what the event was and conversion of this
description into a usable form. The abstract notion of this usable
form we can call an Event Object; note that this does not
imply the used an Object Oriented language; I am simply using the
word object to represent a transferable contained amalgamation of
function, data and information.
Also note that gathering and conversion can actually occur in
either order or simultaneously or any intermediate of these
possibilities.
Event dispatch: is a system which forwards
event objects to event handlers based on some rule set.
In theory, all event handlers could handle all events (no routing
on the part of dispatch); however, this would simply result in the
role of event dispatch being distributed across all the handlers
because in such an architecture the handlers would need to ignore
some events based on rules. Distribution of the 'ignore'
functionality over multiple handlers would then make the system less
functionally normalized (see later) and so is not desirable.
Event handlers: are entities which respond to
events.
Event handlers should be in a functionally normal form. I.e. one
should not have the same functionality represented in more than on
event handler and the events of a given, unique type should only be
dispatched to a single handler. If a publish/subscribe mechanism is
to be used, it should be applied by the handlers publishing to some
further architecture not at the level of event dispatch and handler.
These normalization provisions are to avoid contamination of the
event model with implementation detail and, in general, to reduce
the complexity of the model to its irreducible form thus making it
maximally tractable.
What is an event?
The discussion so far describes the over all structure of the
model whilst being very brief about what an event actually is. To go
further with defining events we must first understand the context in
which we will define them. This context must be finite or else our
model will explode with complexity, to this end I will introduce the
concept of Domain. The model domain contains all the
aspects of a system which we wish to model but nothing else. Such an
idea is flawed at its inception because nothing in the physical
reality (as opposed to the a-priory, tautological realities)
is completely separable from anything else. Nevertheless, the event
modelling effort is motivated by a need for tractable models;
creating artificial domain boundaries is a key tool for helping
achieve this tractability.
Given the enclosing notion of a modelling domain, we can now go
about defining what events should be. The following list is
sufficient but not item unique; in other words, the different
requirements of the event do have overlapping meanings, but when
taken together, are sufficient to fully describe what an event should
be:
Information Domain Sufficient: They should
contain sufficient information to fully describe their roles in the
domain being modelled. No other data or information should be
required. Specifically, if the notion of a 'context' for an event or
a modelling of an event's raising entity's state is required then
the event handler has been contaminated with the event
raiser/marshaller. Such contamination leads to a destruction of the
pure event model and loss of its benefits.
Domain Atomic: Events should not rely on
information from other events to be information sufficient. This can
be seen as the corollary of being information domain sufficient.
Domain Unique: Within a given model domain, any
event must be of a type which is totally unambiguous to all other
possible events in that domain. If the meaning of an event can be
confused with the meaning of an event of a different type due to
ambiguous type resolution then the events are not unique. As we
cannot rely on context or state analysis to provide event
disambiguation, all events must be self unique.
Data Domain Normal: The data contained in an
event object must be sufficient to circumscribe the sufficient
domain information and nothing else. Excessive information leads to
excessive complexity. Similarly, data replication leads to excessing
complexity for the same information content.
Also of interest, event handlers should be in functionally
normal form. I.e. one should not have the same functionality
represented in more than one event handler and the events should only
be dispatched to a single handler. If a publish/subscribe mechanism
is to be used, it should be applied by the handlers publishing; it
should not be done at the level of the event dispatch and handlers.
These normalisation provisions are to avoid contamination of the
event model with implementational detail to reduce complexity in the
model to and irreducible form thus makes it maximally tractable.
Model Transformation: Coping with the real world
So far we have considered event based modelling solely from the
view point of a perfect world. Conceptually, computer science can
occupy a perfect world. A Turing machine of infinite speed and
limitless tape can be programmed to perform any formally computable
operation. Once we make the step into cybernetics we must live with
finites and inaccuracies. We move from a-priory mathematical
tautology to a-posteriori hardware. By way of concrete
example: we cannot realistically redesign the human heart to allow it
to raise events; we must monitor it and then raise events based on
changes in detected state. Equally, we are unlikely to have the
resource or even the legal right to reconstruct the Windows kernel
such that it will raise events for all status changes in which a
sophisticated monitor may be interested; again we must fall back to
monitoring via polling and additionally merging in of some raised
events which are available to us. Other systems may raise events
contain inappropriate information or are in a different domain to our
model.
From this we can see that to create a pure event model in real
world cybernetics we must employ transformation from the observable
space to the pure event space (by analogy to the transformation from
time to phase space which is so vital to the analysis of chaos).
Event Transformation: Merging And Splitting
Whist we can now realise the need for transformation we should not
loose sight of the benefits of event based modelling. Thus I propose
here an event based view of how we may perform the required
transformation and from that some (hopefully) useful hints as to how
we can implement such transformations in software. To ground this
work, I shall use analysis of real world situations (or their
semi-fictional analogues) to flush out the concepts required.
Let us consider first a uni-directional event model in which we
wish to understand the load on a compute and how it relates to user
interaction. In this scenario, we see two even raising sub-systems
(human and computer) but all events are in the same direction
(computer/human to monitor). After that, I would like to investigate
modelling full bi-directional human to computer interaction via a
scenario based on fictional a database management script. The second
example is a member of an interesting set of challenges in which
cybernetic systems have been created based on a state model where the
human navigates though cyber-states via a set of questions and
answers. Such systems are particularly complex to model using non
event based techniques because of the bi-directional communications
and the consequent two separate stateful sub-systems navigating their
way around related by different cyclic directed state graphs. Other
examples of this set of challenges are humans driving cars or
auto-pilots flying aeroplanes.
Merging And Splitting As Applied To Polling Based Monitoring
Step 1: What in what are we interested (define the domain)?
Step 2: What events are available to us?
Step 3: How can we transform this to match our domain?
We are interested in the changes of state of processes on the
computer and any temporal relationship between their distribution and
those of events from human interaction. An initial guess at the
events in which we may be interested are:
Disk access going above 1 megabyte
per second.
Disk access going below 1 megabyte
per second.
CPU consumption raising to greater
than 90% for greater than 10 seconds.
CPU consumption dropping below 90%
in the last 10 seconds.
Human launching an application.
Human shutting down an
application.
Human requesting file delete from
a file manager.
Human requesting file move from a
file manager.
Human requesting an application to open file.
The first thing to note is that the events raised from the
computer sub-system are transitions whilst those from the human
sub-system are simple actions. This can be thought of as a
consequence of the human interactions having already been transformed
into events before we are aware of them in our observations (we are
not seeing the internal workings of the human's brain); conversely we
are converting the state of the computer sub-system into state change
events. We will see later that these two can be seen as nodes and
edges of a state graph respectively.
Next we can start to work out how we might acquire the computer
sub-system events. It is pretty certain that these events are not
already raised or even raisable by the software in the operating
system (OS) of the computer. I am going to make the assumption that
we are going to have to poll some internal states within the OS
kernel. Let us consider the criterion that the disk access has gone
above 1 megabyte per second. If we have a conjecture that the OS
stores the number of 8 kilobyte blocks it has written to disk in the
last 100 milliseconds then we have to use this information to create
our events. How do we convert this state into events?
To do this we must consider the domain and event model first and
the state second. It is far too tempting to design a model from
the sub-system upwards rather than from the domain downwards. So
for a start we need to convert the 'how many 8 kilobyte blocks in the
last 100 milliseconds' into events. We do not have to try too hard,
we can just create a 'the state is this' event every 100
milliseconds; we can do so by simply polling the state of the kernel.
The events thus created are in the wrong domain for our model and
thus do not meet our criteria:
Domain atomic: No, the set
of these events contains repetitions of nodes (static state) and we
are interested in edges (state change).
Domain unique: Yes, they
all have a simple type and that type is unique. They are all of
'disk I/O was' type.
Data domain normal: We
don't know yet - that is more implementational than we are
discussing here.
Information domain sufficient: No, they do not contain
information on the change of state. Because they are not atomic they
are inevitably information insufficient.
The solution to all these problems is to merge the events. We can
create an event handler which also acts as an event raiser. It is
impure in that it does store some state; however, it purifies the
event model by discarding the need for state storage in the handlers
of the events it raises its self. It stores the 19 previously raised
polling events. If the first ten give an accumulated disk access of
less than 1 megabytes and the second 9 plus the current event give an
accumulated access of more than 1 megabyte, then an event of type one
(above) is raised. If the opposite pattern is detected, then an event
of type 2 is raised. These events do not store the actual amount of
disk access (that would not be data domain normal) just that it has
changed. We will also want to store in the event the time it changed
because we have now put an appreciable delay between the event
raising situation (notionally after the first 10 polling events) and
the event actually being raised. Further, accumulation of timing
errors is likely. Finally, time could prove important in analysis of
the human interaction events against OS events.
To illustrate the counterpart to event merging, we can now
consider event splitting. If we were to find that the polling events
actually contain a list of all the processes and their disk I/O then
we will need to do this very thing. Indeed, this is a very likely
scenario, because without the events being created in this way, how
would we be able to monitor newly created processes? An alternative
would be to poll and create events which list all the running process
and then poll for each process.
The approach is again centred on understanding the domain and
basing everything on events. We can view the polling events as
actually being a collection of events which have been merged. We
simply split them into their separate events (one per process) and
then pass these split events into the event handler for single
process events which then does the state tracking and event merging.
This splitting is again, done in an event handler which then raises
events.
We have thus created a model which is entirely event based
throughout and eventually emits fully complient events into the final
marshaller/dispatcher/handler model.
An overview of the final event model for our OS monitor
using
merging and splitting.
I will not labour this example any further because I believe all
its key issues have been covered. However, it still stands as a
possible straw man to be pulled to pieces in later (not in this
document) analysis.
Analysis of the bi-directional stateful system
A visualization of a cyclic directed graph.
Given the success of splitting and merging in the previous
example, one might ask if we can use the same techniques on the more
complex second example. To do this I will first bring into the open
the idea of graphing to which I so far only eluded. The idea is that
we can view the state of a cyber-sub-system as a cyclic directed
graph. This is a formalization in that real physical systems cannot
be viewed as fully deterministic; even if one assumes that there is
no random element to physical reality, chaos shows that finite
measurement error prevents fully deterministic modelling. However,
the cyclic directed graph is a useful metaphor at the very least. We
can use it in either one of two ways. Both assume that the graph is
graphing state. Nodes are known states and edges show transitions
from one state to another. The known states being resolved within the
domain of the model. In other words, if the model is not concerned
with a variable X in a program, the changes in X would not cause
transitions between nodes.
If we are interested only in the instantaneous state then we can
raise events as the sub-system arrives at a node. If we are
interested in the transitions between states then we can raise events
as the system passes along an edge. But:
what are these events and what data information do they
contain? To answer this question we can go back to considering for
what we are creating our model. The temptation is to create events
based on our understanding of the event raising sub-system rather
than (the correct) approach of considering the model and its domain.
By example: Let us consider a state change of a 4 digit unsigned
integer. We can imagine an event of type 'IntVarChange' which holds
data in which are 'previous-value' and 'current-value'. This event
models that the state has changed but is type ambiguous as to the
values of its data. Alternatively one could have one hundred million
different types of event, each one unambiguously defining the
previous and current value of the state change via type alone.
Neither of these approaches is wrong. However, we can work out which
is appropriate for our model:
Will the event handler do something different depending on
data values? This is a weak reason for having different types.
Will the resultant model have an intractable number of
different event types? This is a strong reason for not having
different event types.
Will different event handlers be used for different values.
If the answer is yes, and the handlers are functionally normal, this
is a strong reason for having different types.
Reality may be anywhere between these two extremes. I feel it is
up to taste and skill to resolve the issue further.
Back to the example
The cyclic directed graph of our notional example program.
Let us look once more at our database control script. We shall
give it the above state graph. This is a simple example; however, the
cyclic nature of the graph is apparent: Attaching a database file to
a schema will alter the choices available for backup and restore and
so on.
So, what questions should be ask to start the analysis process?
Are we interested in the nodes or the edges? The answer is
nodes with the extra proviso that we may need to accumulate
information all the way along the edge and store this in the event
object. The script's questions act as points to raise events. We can
define the questions as being complete when the script stops and
waits for input. i.e. when it 'asks' the question.
What information do we want to be contained in the nodes? Can
we make a general description – a set of guide lines –
and apply this to each node? The answer is yes to the guide lines.
We should include in the events information which is dynamic and
meaningful. i.e. the information has meaning to the event handlers
and which is able to change between instances of the event.
Information which is static (unchanging across all possible
instances of a given event type) should not be included in events
but should in represented, if of meaning to the event handler, in
the appropriate handler. If such static information does not seem
appropriate in a given handler then the chances are that the events
or handlers are not properly normalised.
Event Chaining, The Bi-directional Model
Now we have some idea of how to convert the script sub-system's
state graph into events, we should look at how to managed human
interaction as events can how to understand the temporal relationship
between the two. Whilst our model does convert a cyber-state graph
into a set of separate events, it is not true to say that these
events and be raised in any order. Whilst this may be fairly
intuitive of the script's graph, it is possibly less so of the human
graph. In theory the human could raise any possible event at any time
and in any order.
Our model's domain is that of the question and answer interaction
between the script and the human. In this domain, human events only
exist as responses to questions. This means there is a temporal
relationship between an event raised by the human and that raised by
the script. To understand what event a human legally can raise in the
domain we do not need to know the state of the script (that would
break the pure event model approach). All we need to know is the last
event raised by the script. Any given event from the the script can
only be followed by a sub-set of all possible events raisable from
the human.
This approach works equally well in reverse. For any given event
raised by the human (as long as unique typing is enforced) we can see
that there is a sub set of events which the script can then raise.
So, a complex system of two independent cyber-sub-systems can
actually be reduced to two sets of events (script and human raised)
and single step temporal chaining relationship between the members of
the two.
Splitting And Merging
If we were to wish to alter the human interaction without altering
the underlying script will this model offer an approach or any
guidance? This question takes us right back to the issue of the real
world. In a perfect world we could re-write the script to suit and
changes we have in mind. However, in the real world, we may be unable
to do so for several reasons (for example, it has been security
cleared getting changes passed is prohibitively expensive).
To illustrate how merging might help in this regard, we can
consider the work flow which includes the scripts states 'attach' →
'pick file' → 'pick new schema name'. Using our merging
concepts, we should be able to merge 'pick file' and 'pick new schema
name' into a single event raised by an intermediate between the
script and the human. The human could then respond with a single
event containing the file name and schema name. The temporal
relationship is now between the intermediate raised merged event and
the human response.
However, this idea is not quite as simple as the above paragraph
suggests. The script is not in a position to respond to the single
event from the user and it is not obvious how to merged then events
because the 'pick new schema name' event cannot be raised until after
the response to the 'pick file' event. However, all is not lost. The
solution is:
Raise an 'pick file and pick new schema name' event from the
intermediate when the 'pick file' event is raised from the script.
Let the human respond with the file and schema names.
Split the human response and send the two events to the
script, the first as a response to the already raised 'pick file'
and the second to the 'pick new schema name' events.
If the 'pick new schema name' event is not the next event to
be raised by the script after the 'pick file' (maybe the file is not
accessible and a cancel event is raised) then the second part of the
split event is thrown away.
Such an approach does allow for exact modelling of the system and
the design of ways to alter the system based on the event model. It
also illuminates alterations which are not possible without changing
the script. For example, if the 'pick new schema name' event contains
a datum in it which is dependant on the response event to the 'pick
file' event, then we simply cannot merge and split in the way
suggested above. Thus our modelling approach has successfully
circumscribed what changes can and cannot readily be made to the
human experience without altering the script.
Conclusions
It would appear that the approach works. There are limitations in
its application, however, the model seems to be able to flush out
what those limitations are. I have no doubt the approach requires
further refinement, but I also have no doubt the effort will be
rewarded.