This article presents a proposed debugging view for the Eclipse IDE, known as the Visualizer View.
A bugzilla entry has been created to track the progress of this effort:
Bug 335027: Visualizer View feature
The existing Debug View in Eclipse consists of a simple tree structure, displaying launches, processes, threads, stack frames, etc. in creation order. The Debug View allows selection of a process or thread of interest, and allows actions to be performed on the selected entity, such as suspending or stepping. The Debug View also serves as a selection source for other views: a selection in the Debug View triggers updates in the source code view, variables view, etc.
This presentation is suitable for the very common case where the developer of a multicore application views that application merely as a "bag of processes" and does not really care how they are scheduled on the physical hardware, beyond perhaps ensuring that multiple worker processes are not competing for the same resources.
There are other possible presentations, however. These include:
- a more concrete view, where the actual layout of tasks on hardware is shown
- an application-centric view, where the layout is a graphical representation of the parent/child or functional relationships between tasks
- other possibilities, which require more than a simple flat (or hierarchical) listing of tasks
These presentations, or visualizations of debugging state, suggest the need for a Visualizer View, which can be used to present and possibly select from the available visualizations.
This Visualizer View should not be viewed as a replacement for the Debug View, but rather as a complementary perspective on the same application. To give an analogy, in writing a technical article one does not dispense with the text of the article and merely present a graph; one uses the graph to cogently present an overview of the details discussed in the article. Similarly, the Debug View might still serve as the "main view" of a debugged application, but one might also use the Visualizer View to get a different, high-level perspective on the same application.
In creating any such visual presentation of debugger state, one needs to
- present an overview of large numbers of elements in a compact, yet accessible form
- make important things (e.g. suspended/crashed processes) stand out, while giving a clear sense of the overall state (e.g. all other processes are fine)
- allow the user to select and interact with these elements in a straightforward way
Tilera's Grid View
A specific example of a concrete, hardware-centric visualization is the Grid View extension added by Tilera Corporation to its Eclipse-based IDE.
The figure below is a screenshot of the Grid View, showing an application that consists of a number of processes distributed across "tiles" (or cores) on Tilera's chip. The tiles are indicated by the squares in the grid, hence the name "Grid View", and the processes/threads by colored "dots" within the squares. Each process/thread "dot" is further annotated with its Linux task ID. (Not shown is a tooltip displayed when one hovers over a tile or process, providing further detail such as the executable name.)
In this example, the application is stopped at a breakpoint (hence the overall yellow coloring of the hardware elements) and one process has "crashed" by raising a signal. (This is the process "dot" on the red tile with the blue selection ring around it.)
Other elements to note in the Grid View display are:
- the I/O and memory elements around the edge of the grid
- the task (x,y) coordinates indicated at the top and left edges
- the overall application state, displayed as text at the top
As noted above, the Grid View does not replace the Debug View. Rather it complements it, by presenting a hardware-oriented view of the layout of the application. In the Tilera case, it might happen that the arrangement of processes on tiles, or their proximity to various I/O devices is of interest. At the very least, the Grid View provides a quick visual confirmation that there is at most one "worker" process scheduled to a tile. (On the red tile, the parent process and a worker it has forked are momentarily sharing the same tile.)
The Grid View also allows selection of processes/threads. In the figure above, in the top-right corner two processes are being drag-selected using the marquee-style selection box. The view's toolbar buttons for pausing, stepping, etc., mimic the corresponding buttons on the Debug View, and apply to the currently selected process(es). (More precisely, they correspond to processes that have an associated debugger, indicated by a small "D" mark next to the process.)
Finally, the Grid View also serves as a selection source for other views. The selected process(es) or threads in the Grid View are automatically selected in the Debug View, and views that are dependent on the Debug View selection are implicitly updated as well. Similarly, the Grid View is "selection aware", so a selection in the Debug View causes the Grid View to update its selection accordingly.
This is an example of a useful synergy between the two views: in the Debug View it is not immediately obvious which process is assigned to which tile, but by selecting a process in the Debug View, one can immediately see from the selection in the Grid View which tile it is currently associated with.
The potential hardware/application types that would want to be supported by this framework are:
- A highly symmetric, many-core platform with a specific 2-D hardware layout, such as Tilera's chip.
- A symmetric, many-core platform with a large number of cores, where the layout is not essential -- in other words, a generic parallel display.
- An asymmetric, SoC hardware platform.
- Possibly multiple hardware components ganged together.
TBD: Suggestions are welcomed, as well as more detail on the latter cases, as the author's background is heavily biased towards symmetric and massively parallel hardware platforms!
The guiding debugging tasks for this proposal are:
- Default Visualizer View state: - The Visualizer View can exist when there is nothing to be displayed. In such cases, it should have some initial "default" display, for example, a blank view or perhaps a guiding message. ("Please invoke a launch", etc.) This can be left to each of the selectable presentation(s), but this case should be taken into consideration in the design of any such presentation. - Debugging a multi-process/thread application in a symmetric environment: - When the user launches an application, the Visualizer View should update to reflect that launch. Note that the launch does not have to be invoked in Debug mode -- the Visualizer should work just as well for non-debugged applications. - During execution, with some periodicity, the Visualizer View should update to reflect the current state (or at least a snapshot) of the application as known to Eclipse/GDB at the time. There will necessarily be some skew, but this is permitted, since the goal is to allow a rough sense of where the application is. - The Visualizer (or rather each presentation) indicates somehow which of the visible elements can be operated on by debugging actions. This might be a marker of some kind that shows where debuggers are attached. - When execution is suspended "normally" (e.g. at a breakpoint) the Visualizer should update to reflect the current state. At this point we want the presentation to be as current and accurate as possible. If we're debugging in an environment where some processes are allowed to continue execution, it is permissible for only the suspended processes to be up to date, and the rest are displayed based on their last reported state. - When execution is suspended due to a crash, the Visualizer should update to reflect the current state. The crashed process(es)/thread(s) should be indicated. - Switching between launches - When the user changes the launch context (i.e. by selecting a different simultaneous launch in the Debug View) the Visualizer View should update to reflect the selected launch's state. - When a launch is removed from the Debug View, if it happens to be the one displayed in the Visualizer View, then the state of some other launch should be displayed. (Which one to display is somewhat arbitrary, but it is suggested that it should be the next most recently viewed launch. We might also use the current Debug View selection to determine which launch to display, though this provides less determinism about which launch happens to be selected next) If no other launch is available for display, the Visualizer View should return to the "default" state of the currently selected presentation. - Selection in the Visualizer View - The user selects a set of debuggable elements (e.g. processes/threads) in the Visualizer view. The Debug View selection updates as a result, causing its dependent views to likewise update. Where more than one such item is selected, the item(s) selected depend on how the Debug View and its subsidiary views handle multiple selection of the selected elements. - If selected items in the Visualizer View do not directly correspond to Debug View elements (for example, if the user selects a tile), then related Debug View elements are selected (for example, the process if any that is currently on that tile). - Selection in other views - The user selects a process, thread, etc. in the Debug View. If this corresponds to one or more elements in the current Visualizer View, then the view updates its own selection accordingly. If no such elements exist in the visualization, the selection there is cleared. - Actions on selections - The user selects one or more processes, and clicks, for example, "Suspend" in the Visualizer's toolbar. This should be the same as invoking the Suspend action in the Debug View for any process(es) that have debuggers associated with them. Processes that do not have debuggers are unaffected by the command. (A possible alternative is attaching debuggers to any such processes, but this may involve too much overhead to be practical.) - Context Menu support - If the user right-clicks on the Visualizer View, the click location is used to determine the contextual item, if any. For example, the user may right-click a tile or a process/thread icon. (Alternatively, the current selection, if any, is treated as context.) A context menu with appropriate commands for the context, plus any "global" actions, is displayed. - Switching between presentations - The user runs an application, and selects items in the current Visualizer presentation. The user then switches (via tab or other control) to a different presentation. The new presentation should update (or already be updated) to reflect the current launch and the current selection if any.
The Visualizer View, as here proposed, should not be thought of as a specific visualization, such as the Grid View, but rather as a framework. The Visualizer View should support multiple graphic representations of the current state of an executing application, and allow selection of items and invocation of actions on that application. It should also allow the user to easily switch between the available presentations.
We should also consider allowing multiple views, each of which could present a selected presentation, and supporting pin-and-clone so the user can "lock" a given view to a specific launch and/or presentation.
As noted above, a given visualization can be highly concrete, e.g. an exact representation of the processing hardware showing the layout of the application on it, as in Tilera's Grid View. It could also be highly abstract, e.g. a graph representation of the processes/threads of the application, showing their parent/child relationships.
One important motivating instance of this is displaying and allowing control of an application with one or more debuggers attached to its processes. So for example in the Grid View, a marker (a small "D") is used to indicate processes with associated debuggers, and the toolbar operations of the view are oriented towards control of these debuggers (stepping, suspend/resume, etc.)
Something else to note is that we distinguish visualization views (such as the Debug View or the Grid View) from detail views (such as the Variables View, the Memory and Disassembly Views, etc.) which provide detail or related context based on the current selection. The intent of a visualization is to provide the "big picture", while detail views like those indicated above provide a narrower, focused view of the selected element. (This is a broad classification, and it's not impossible that the selected element could itself be complex enough that such "detail views" might themselves require some kind of visual representation, but for now we exclude this possibility.)
The Visualizer view should consist of:
- The Visualizer view itself. This should support periodic and on-demand updating of the display, in response to: - user actions, like resizing the view or requesting an update</li> - event(s) from the model ("push" model)</li> - periodic updating of the view ("polling" model)</li> - A provider-based "presentation" mechanism for display of the model, its elements, and their current state. - An application-specific "model" object hierarchy. Ideally, this is just the application model itself, i.e. objects representing processes, threads, tiles, etc. The model classes themselves should be entirely presentation-agnostic. The presentation model is responsible for the mapping from model to view elements. - A description of the target, in a presentation-neutral format, which captures any important layout information that would be useful. (The internal structure of the hardware, connections between elements, etc.) - An update framework for reflecting changes to the model state. Examples: - rescheduling of threads to new tiles - changes to thread state (running, paused, stopped at breakpoint) - generated model state (e.g. current processor cycle, aggregate amount of memory in use, other on-the-fly performance data; in general stuff that isn't associated with a specific event, but wants to be periodically updated) - Some kind of "backend" interface, by which the model can receive information about the target and its current state. (This may also serve as a source for the target description and update events described above.) - An action framework for performing operations on the model and its elements. (Ideally this would be the existing Eclipse action framework.) Examples: - stopping/starting debugged processes</li> - attaching a debugger to a process on demand</li> - opening a console pane associated with a specific process</li> The action framework should support not only toolbar items for the view, but context menu items displayed on the Visualizer View's context menu. - A context menu mechanism, by which context menu items can be registered "globally" (e.g. for the view as a whole) and presentation-specific items added on the fly, based on the right-click context and/or the current selection. - Other requirements: - Support for multiple different user-selectable presentations (e.g. a hardware view vs. a more abstract "application" view). - The ability to select element(s) of the model and have that selection be made available to the workbench as a whole, and via the Debug View selection mechanism in particular. (Note: this probably requires defining some mechanism for mapping visualization elements to objects that are "known" to other views, such as debug targets, processes, etc.) - Acceptance of selection state provided by the workbench, and auto-selection of corresponding elements (if any) in the visualizer view. - The Visualizer View should support pin-and-clone, so a user can have multiple views open, each pinned to a given launch and presentation. - The Visualizer view should support Grouping and Hiding, like the Debug View. Such a feature might redefine the current layout based on hidden items and on grouped items. (Note: we might specify that visibility/grouping are model properties, and a presentation is free to present these properties in whatever way makes sense.) - Support for a concept of zoom-level, i.e. being able to enlarge/shrink the view to see more context or more detail. To some extent this may just be a presentation thing -- one presentation might scale itself based on how much screen real-estate it's given, another might treat that real-estate as a scrollable view over a "zoomable" visualization. - Support for new display properties/behaviors. For example, we might extend selection to support the notion of 'locked' or 'protected' elements. The user could select elements in the Visualizer and mark them protected. The protected elements would be excluded from operations (e.g., suspend, resume) even if they are selected. (This simplifies selection, and can help a user avoid making time-wasting mistakes by resuming the wrong entity, etc.) This may be nothing more than the requirement that the set of model properties a presentation has access to be extensible, and the presentations themselves able to be modified to make use of newly defined properties.
The visualization framework will want to include the following classes:
. VisualizerView - This is a standard Eclipse view, which contains a viewer and actions, and interacts with the workbench as usual - We might provide a base "VisualizerView" class, which handles most of the boilerplate view stuff. - Alternatively, we might just present some examples of how one can implement a view that makes use of the other classes below. (In the case of Tilera's Grid View, the outermost view class is a thin wrapper that holds the equivalent of the Viewer class and mainly handles toolbar actions and the context menu.) . VisualizerViewer - A "canvas" style control that displays the view contents of the currently selected presentation - Should be arbitrarily scalable in width/height. - Should decide when to update itself based on user resizing, etc. - Should provide a method for requesting an update, and "batching" requests (e.g. by using a timer to periodically check whether an update is needed) - Should also support tool-tip display - Events: - move move/drag (to allow rubber-banding/marquee display) - point/region selection - element selection (using providers to decide what got selected) - context menu action - Question: who creates the viewer elements? Does the presentation decide what represents what, or does the view "walk" the presentation view of the model and assign one element to each walked child? . VisualizerViewerElement - Graphic display element, base class for view elements of various presentations - This is not a UI component, it is simply a class/interface that knows how to draw itself given an appropriate graphic context from the VisualizerViewer. In fact, it might be better to implement this as an interface, so that we don't tie the user to a fixed base class. (We might still provide a sample implementation base class that does something simple, of course.) - Viewer (or rather current presentation) sets the bounds of this element based on its own size, then the element decides how to draw itself within the space it's given. - One could also abstract out scaling of elements to the canvas, but in general the result looks uglier than if an element draws itself based on its size and can decide when to simply stop displaying labels, details, etc. because it is being drawn too small. - should provide methods for - determining whether a click point is contained in the element - determining whether a selection region contains/overlaps the element . VisualizerPresentationManager - Manages set of presentations for VisualizerViewer - Question: how is a presentation selected? Should the selection UI (if any) be part of the presentation itself, so it can be defined by the user? Or should we provide a tab panel, etc. mechanism, like in the Memory view? . VisualizerPresentation - Represents one possible display of the current visualizer model - Includes methods for obtaining the model object and navigating its structure. - Provider based, consults list of VisualizerPresentationProviders to find one that knows how to present the current object. - Provides context menu actions for the presentation as a whole . VisualizerPresentationProvider - Presentation for an element (the whole platform or one of its hardware elements, etc.) - Knows how to present the element itself, given its size. - Provides methods for accessing the element's parent/children. - Provides any element-specific context menu items - This allows the model object to be an arbitrary tree-structure, perhaps even the existing object model, with no need for an extra "model" hierarchy. - It also makes changes to the model easy -- just add a provider for any new object type. . VisualizerContextMenuManager - Manages construction of context menu for Visualizer View - allows registration of "global" context menu actions, always displayed - polls the current presentation dynamically for any additional, context-specific actions to present . "Visualizer Model" Object - Root class of tree structure representing platform, etc. to display - This can be any object, the VisualizerPresentation encapsulates how it is navigated and presented. . A "model descriptor" data structure that captures important aspects of the target platform's layout (core "grid", IO devices, etc.) This should be in a presentation-agnostic format, and serves as a guide for presentations that want to provide a realistic hardware layout. A presentation is permitted to summarize, paraphrase, or ignore this information as needed, based on what it intends to show. . A "backend framework" by which the model and/or presentation can receive updates on the target's state. (This might include the model description noted above.) Note that this framework should not be directly tied to the visualizer view -- ideally, the backend informs the model, and the model (though appropriate update events) triggers an update in the view. We do need some standard framework by which a given target can tie its backend into the visualization mechanism.
"Hardware Visualization" Instance
It is suggested (though not required) that the Grid View, or a similar hardware-oriented view, should serve as a specific, motivating example of a visualization style to be supported by the above framework.
Since there is no one "right" visualization for all possible hardware types, what might be required is either:
- a prototypical example that could be modified or extended to suit the hardware layout(s) in used by a particular implementer.
- or a generic "hardware view" that supports some kind of description language that specifies the layout of elements and identifies them for the purpose of assigning update events to them
(TBD: Need more detail here -- use cases welcomed!)
Implementation Considerations / Design Choices
For the Visualizer view and element classes, we might consider specifying/using a plugin that provides graphic elements and view support, for example GEF (http://www.eclipse.org/gef/) to reduce the coding needed to construct a presentation.
However, this has the consequence of making that plugin a requirement for CDT and/or base Eclipse, so we'd need to be sure it was the "right" one. There is a precedent for this: the remote launch plugin requires RSE.
Perhaps the Visualizer framework may not specify or require such a plugin, but a specific visualization instance, such as the Grid View, might do so.
Alternatively, we might have the framework leave the choice of implementation entirely open, and provide some useful examples in various frameworks like GEF to show what's possible.
TBD: Does the Parallel Tools Platform (PTP, http://www.eclipse.org/ptp/) have a similar view, and/or is there any possible synergy here?
Comments To Be Factored In
If you have comments and/or suggested requirements, please either add them to the bugzilla Bug 335027: Visualizer View feature or below, and we'll factor them in as this document is updated.