How to Execute Software Behavior Faster than (Wall Clock) Time
What exactly is time? Well surprisingly time is much harder to define than one would imagine without there being a circular reference to time itself. Here is a definition from Wikipedia:
Time is a dimension in which events can be ordered from the past through the present into the future, and also the measure of durations of events and the intervals between them…Some simple, relatively uncontroversial definitions of time include “time is what clocks measure” and “time is what keeps everything from happening at once”
So at the heart of the answer is the ordering of events which prevents everything from happening at once. Sounds very much like a discrete event simulation. It is this thinking that has some scientists looking to answer the question whether we ourselves exist in some computer simulation.
“The problem with all simulations is that the laws of physics, which appear continuous, have to be superimposed onto a discrete three dimensional lattice which advances in steps of time.” - The Measurement That Would Reveal The Universe As A Computer Simulation
What about the time interval between such ordered events, especially ones in which one event causes another event to occur as in a caller method invoking a callee method? Well we only need enough time to pass between them to maintain the cause-effect relationship between them, preventing the “happening at once”.
In my last post I showed how JXInsight/Simz can be viewed as a Matrix like computer simulation for application runtimes, replaying the execution of instrumentation calls in a connected application runtime within a simulated runtime in near real-time. But if we eliminate the near real-time constraint altogether we can go much faster and slower at different time intervals (from our observer perspective). In fact we can speed up things incredibly fast by having the simulation engine playback a previous recording. What if we simply reload a recording into an application runtime? Why stop there when we can reload a recording and transmit the events emitted from its playback over to a simulation engine which in turn playbacks, in what it assumes is real-time. To experience time this way click on the image below to playback a screen recording – Matrix style.
The Oracle: You have the sight now, Neo. You are looking at the world without time. – The Matrix Reloaded
In the screen video above two scenarios were played out. The first involved a normal Java client application (code listing below) being dynamically instrumented and metered with the resulting metering event collection sent to a remote Simz service as well as stored in a binary log file. The Simz service had the matrix terminal visualization plugin, introduced in the blog posting titled “Plugin to The Matrix for (Virtual) Machines — Simulated Threads & Stacks”, installed to more easily demonstrate the speed difference across the two scenarios.
In the second scenario the metering log recorded during the execution of the first scenario was replayed by a playback component built into the metering engine. This playback component read each binary record logged and then simulated the replaying of the Probes Open call, including the same meter readings (clock.time in our example), by executing threads much like how the Simz service operates. The playback operates much like a metered application runtime so its metering could also be feed to a remote Simz service, which is what actually happened. What is important to note is that the playback executed far faster than the original application – both in the playback runtime as well as in the remote simulated runtime. Whilst the meter readings of the wall clock time would have remained the same across both scenarios our observation of time (passing) was different.
Why is this incredibly useful? Well it allows us to reconstruct the execution of software behavior and perform ad hoc queries on such behavior in flight (and within the thread context) that go far beyond the primitive options possible when behavior is reduced to data records in a relational database. These are the same type of complex queries that can be performed in real-time within actual application via the
interceptor extension points. You don’t need any temporal query language extensions because activity metering events are replayed out again by the very same threads (simulated versions) that fired the instrumentation hooks just like in the real application runtime. Finding the caller chain of an event that exceeds some threshold is as simple as calling
Probes.context().getStack(). Comparing the current thread event metering with its cumulative average up to that point in the execution involves simply calling
Probes.context().group(probe.getName()).metering(CLOCK_TIME).getAvg(). You can get the same question answered across an entire cluster of application runtimes by dropping the context as in
Probes.group(probe.getName()).metering(CLOCK_TIME).getAvg(). You can introspect behavior the very exact same way you would do if the application and its threads were executing for real at a particular point in time. This self observation capabilities post execution is even more impressive in that you don’t need for the software itself to be present. Recordings offer a time machine for behavioral analysis that is completely disconnected from the lifecycle of the application code base. Plugins and extensions can relive the events of the past just as we do in our dreams (but without the noise).
And if we don’t phrase the question the right way the first time we can always change it and replay out the sequence again and again until we finally crack it. Ground hog day with the fast forward pressed!
The Oracle: Because you [Neo] didn’t come here to make the choice, you’ve already made it. You’re here to try to understand *why* you made it. I thought you’d have figured that out by now.
I could have easily replayed the metering recording without enabling the
simz metering extension.
I could also have configured the Simz service to record the metering of multiple application runtimes sending their metering feed to the service for simulated replay in near real-time. The replay would then have represented the ordered behavior across an entire cluster from the perspective of the observer – the simz service.
Appendix A – Code Listing