Tuesday 21 August 2007
I'm very pleased to announce the release of Chronomancer, an Eclipse-based UI for Chronicle. I'm releasing it under MPL 1.1. Thanks to Mozilla for letting me do this.
As I mentioned in my last post, we successfully used Chronomancer last week to track down a bug in Gecko's cycle collector. I think that means this is the right time to release it in the hope that other people will find it useful or interesting, even though it is still far from complete. Release early, release often and all that. I also hope that people will be interested in contributing, since I certainly don't have enough time to do a lot of work on it.
I have posted a screencast of Chronomancer in action, debugging the cycle collector bug. I apologise in advance for my mumbling and backtracking and the general roughness of the demo; I don't have time to make it great. I hope it communicates the power of the tool.
Chronomancer has the following features:
- A Timeline view that shows events of interest, such as function calls and memory writes; time increases from top to bottom. Function calls display their parameter values. Clicking on an event makes it the "current event".
- The Timeline contains two buttons, one to connect to a Chronicle database and another to close the connection.
- The Timeline's dropdown menu lets the user add new queries to the timeline. Currently the only available query is to find invocations of a named function.
- A Call Stack view that implements history-based stack reconstruction to display a stack for the current event. Each stack frame shows the parameters to the call at the time when the function was invoked. Double clicking on a stack frame adds the start and end of the function call to the timeline, and also adds a "caller" event to the timeline and selects that so you see the context in which the function was called.
- A Locals view shows the values of local variables (including parameter values) for the currently-executed function.
- A Data view shows the values of chosen variables in memory. Double-clicking on a pointer in any view will add the target of that pointer to the Data pane. Whenever the current event changes the Data pane updates to show the values of the variables at the chosen time.
- The context menu for variable values includes "Find Last Write" and "Find Next Write" commands. Currently these commands only work on variables in the Data pane (fixing that isn't too hard but I haven't gotten to it yet).
- Chronomancer will open source windows to show the current line, if you create an Eclipse project containing the source files. (You can do this fairly easily for most C/C++ projects, and you don't have to use Eclipse to build or edit your code; see Getting Started in the Chronomancer wiki for more information.) The current line is highlighted in green. Other lines in the function that were executed in the same function invocation are highlighted in amber. For function invocations containing loops, the loop head is highlighted in red and only the annotations for the current (or nearest) iteration are displayed. (It would be easy to add commands to display other iterations but I haven't gotten to that yet.)
- The context menu for the vertical ruler in source panes has two new commands. "Show Callees" adds all callees for the executed line to the timeline so you can work with them. Chronomancer automatically descends into the first callee. "Set Current Line" adds the executed line to the timeline and makes it the current event; this is handy for displaying the values of variables at that point. (Stepping --- in either direction --- is obsolete!)
- The dropdown menu for all Chronomancer views contains a "Copy Contents" command that copies the view contents to the clipboard as text --- invaluable when you want to copy a stack trace to Bugzilla, for example, although with a bit more work copying a Timeline or Data pane to Bugzilla would also be interesting.
There is some interesting stuff under the hood. There's an org.ocallahan.chronicle package which provides a convenient Java binding to the Chronicle engine. It does most of the query wrangling on a worker thread so we can run algorithms like call stack reconstruction without blocking the UI. There's a core org.ocallahan.chronomancer package which manages the core Chronomancer state; most of the views and commands are just extensions that plug into that infrastructure. Chronomancer also offers two new kinds of extension points:
- Queries: The only query currently available is finding calls to a named function, but new types can be plugged in via an Eclipse extension point. This allows for project-specific queries (e.g., "Find XPCOM Assertion Failures").
- Type Renderers: Plugins can register renderers for specific C/C++ types. All the current variable rendering is done this way; for example Chronomancer currently includes a custom renderer for PRUnichar* (although this should really be broken out into a Mozilla-specific Chronomancer extension). Type renderers can create arbitrary Eclipse Draw2D widgets, which can offer their own custom UI.
There's so much that could be fixed or added; this was the bare minimum I could do to make something I felt was compelling. I won't even bother trying to list the possibilities right now. Maybe later I'll blog about some of the things that could be done.