In my previous post I have commented a talk on the Time Travelling Debugger by Chronon wich is targeted towards Java. In this post I will describe the architecture of the system and its features.
The architecture of the debugger generally consists of two components: a recorder that is responsible for collecting and storing the execution and program state; and a frontend that is integrated into the Eclipde Debugger UI. The frontend reads the recordings to realize the debug behavior.
As mentioned in the previous paragraph, the frontend is integrated into the Eclipse IDE, actually in the Debugger perspective. Chronon provides a tutorial on how to migrate IntelliJ projects to Eclipse, in order to use their debugger, but a real IntelliJ integration is currently not provided.
Just like with other Java debuggers, users can debug their programs with the well known step-through metaphor and view the values of local variables and arguments. The debugger shows the variables for the current context and their corresponding values in a separate window. Beside watching the values of variables for the current context, users can also inspect the value history of variables and continue debugging with the state that the program had at the time of a specific value assignment (that is cool!). The following figure shows the related UI elements: the variables view in the upper left corner, the editor view in the lower right corner and the variables history in the lower left corner.
In the previous paragraph we have seen the variable history which allows users to step through different program states of the debugged program. The debugger also provides the well known stepping commands, such as step over or step into, but it also allows users to step backwards (step back). With this feature users can do and undo assignments or other changes to the program or execution state on the level of statements. The following figure shows the call stack and the command bar with the debug operations.
In the previous section we have seen the features provided by the debugger and its UI-integration in Eclipse. We will now talk about the backend component which is responsible for collecting and storing the trace/debug data from the running Java program. The following figure shows the involved components and the data flow between them:
The shown components have the following responsibilities:
- Application threads store debug data in the memory buffer (RAM).
- Flusher Threads read the data, do processing on it and save it to disk (Recordings).
While studying the architecture I started wondering how the garbage collector performs with debugged applications. From my point of view this might be the bottleneck, but it seems like Chronon solved this problem:
“It is a well known fact that current JVMs don’t handle heap sizes above 2gb very well. It is possible that if you have an extremely computationally intensive program that Chronon does generate utilize that much memory or that your application already is reaching the 2gb limit and Chronon makes it go over that. To solve this issue we use a custom memory management. Thus even if the data generated by Chronon goes a little high, it wont have a heavy impact on the GC. It is common to see a 2-3gb Chronon heap shrink to a few hundred megabytes within a blink of an eye, which would ordinarily take many seconds or minutes without our custom memory management.”
Chronon designed the bakcend based on the following non-functional requirements:
- Minimum impact on application responsiveness
- Libraray and Framework Independence
The first requirement deals with vertical scaling across multiple CPU cores. The figure shows this by multiple flusher threads. The second requirement deals with the altered performance of the debugged appllication. The debugger instruments the bytecode at runtime to gain the tracing/debug data while the program is executed. The third requirement is related to different frameworks and libraries, such as JEE, SWT or SWING. The debugger provides debugging support, independent of the Java technology the application is based on.
In this article I have shown the features of the Chronon Time Travelling Debugger, how it is integrated into the Eclipse Debugger perspective, the design of its backend component and finally its non-functional requirements.