Introducing ObjectGraphLibrary to visualize Stack and Heap
In this post I'm going to share a custom implementation of classes which can be used to visualize two important parts of memory i.e Stack and Heap.
Introduction
Purpose of ObjectGraphLibrary is to visualize two important memory parts of a process i.e. Stack and Heap. Visualizing memory of a process is much helpful for novice user. Many visualizers have been developed so far to help novices in learning computer execution model and unfortunately no such tool exits either in Windows Phone or in Windows Store on any programming language . Programs of novices are tiny in memory footprint and respective entire memory can easily be visualized so ObjectGraphLibrary is going to present all the available information in memory that is helpful for learning purposes. Before going to implement ObjectGraphLibrary let's discuss important.
Visualizer
Visualizer is a framework of different components that can swap depending on what structure is currently being visualized. It keeps the tracks of different structure in memory, takes care of each structure and decides what data structure will be displayed on user interaction and on what particular location.
Stack
Stack is the regions of memory where data is added or removed in a last-in-first-out manner. In most modern computer systems, each thread has a reserved region of memory referred to as its stack. When a function executes, it may add some of its state data to the top of the stack; when the function exits it is responsible for removing that data from the stack. At a minimum, a thread's stack is used to store the location of function calls in order to allow return statements to return to the correct location, but programmers may further choose to explicitly use the stack. If a region of memory lies on the thread's stack, that memory is said to have been allocated on the stack.
Heap
Stack is the regions of memory where data is added or removed in a last-in-first-out manner. In most modern computer systems, each thread has a reserved region of memory referred to as its stack. When a function executes, it may add some of its state data to the top of the stack; when the function exits it is responsible for removing that data from the stack. At a minimum, a thread's stack is used to store the location of function calls in order to allow return statements to return to the correct location, but programmers may further choose to explicitly use the stack. If a region of memory lies on the thread's stack, that memory is said to have been allocated on the stack.
Stack Frame
A stack frame is a frame of data that gets pushed onto the stack. A stack frame represent a function call and its argument data. The function return address goes on the stack first, then the arguments and space for local variables, and together they make the "frame".
Heap Object
An object that allocate memory area in heap. Heap objects first memory bit address is the address of heap object. However we will use a unique integer to repesent its address so called here "UniqueId"
Implementation
ObjectGraphLibrary implementation contains representation of both Stack and Heap object and their associated objects. Some general data type for collection, dictionary, value object and heap object reference are also implemented in ObjectModel.
Summary of all the the class exist in namespace ObjectGraphLibrary.ObjectModel
is given below:
Name | Type | Description |
---|---|---|
VisualObjectType | Enum | Type of Visual Object |
IVisualObject | Interface | Represents any object that can be visualized |
VisualObject | Class | Represent visualize-able object |
CollectionObject | Class | Reprsenet collection of IVisualObject |
DictionaryObject | Class | Represent Dictionary of Visual Objects |
ReferenceObject | Class | Represent Referance to heap object |
ObservableHeap | Class | Represent entire heap |
ObservableHeapFrame | Class | Represent closely related Heap objects |
ObservableHeapFrameItem | Class | Represent a heap object |
ObservableStack | Class | Represent an entire stack |
ObservableStackFrame | Class | Represent a Stack Frame |
ObservableStackFrameItem | Class | Represent a variable/local inside stack frame |
Almost against each data type there exist an User Interface class in namespace ObjectGraphLibrary.UI.Xaml
. Each UI class has it's own style defined in Themes/Generic.xaml
. Main UI class is ObjectGraphPresenter
that is the actual layout class responsible for visualization. Structurly ObjectGraphPresenter
can be divided into three parts. Stack, Heap and Connectors. Stack is arranged in left side of ObjectGraphPresenter
whereas heap is arranged in right side ObjectGraphPresenter
. Connectors overly stack and heap and connects a heap pointer to the pointed heap object. Connectors are further divided into two parts 1. Stack Connector 2. Heap Connector. Stack connector connects heap pointer from stack region and target heap object. Heap connectors connects heap pointers inside a heap object and the targeted heap object.
Structure of ObjectGraphPresenter is explained in below image.
Drawing Connector Lines
Connector lines are BezierSegment placed in PathFigure. To draw a connector first of all we have to search for heap reference in each stack frame. If any heap reference is found next we have to get it's visual container using ItemsControl.ContainerFromItem
. Using similar code we can get container for target heap object after searching target object in the heap.
To find position of containers relative to parent grid UIElement.TransformToVisual
is handy. Using previous command we can calculate the position of container from origion of parent grid. This calculated position is in negative coordinates. Using Math.Abs position coordinates are converted to signed double. Calculated point is exact position left-top corner of an element relative to parent grid. A BezierSegment with start point of stack container right-bottom corner position and end point of target heap object left-top corner position is added to PathGeomtry. This way we can draw connector lines between stack and heap.
Using similar logic we can draw heap connectors too.
When to draw Connectors
We knows how to draw connectors but question is when to draw connectors?. If we update connectors with each LayoutUpdate then this lead to circular layout update call. According to MSDN FrameworkElemet.LayoutUpdated
is call each time there is a change in visual tree. When an update to visual tree is made we draw connector that also updates the visual tree and leading to circular layout update. If we handle it once then layout is partially updated and some items UI container is null.
If we update connectors on change in items then particular item is not rendered so we can get its position in grid. So, we need a middle way and the way is to set itemUpdated = true when item changes. And in LayoutUpdate handle if itemUpdated is true then en-queue a task to perform when in idle state on Dispatcher. And after completly updating the UI Dispatcher will be idle and executes our task that will render the connectors.
bool itemChanged = false;
protected override void OnItemsChanged(object e)
{
itemChanged = true;
base.OnItemsChanged(e);
}
public event EventHandler ItemUpdated;
void OnItemUpdated()
{
if (ItemUpdated != null)
ItemUpdated(this, EventArgs.Empty);
}
private void OnLayoutUpdated(object sender, object e)
{
if (itemChanged)
this.Dispatcher.RunIdleAsync(FireItemUpdated);
}
private void FireItemUpdated(IdleDispatchedHandlerArgs e)
{
OnItemUpdated();
itemChanged = false;
}
Visual Object Rendering
Visualizer decides what data structure will be displayed and how. DataTemplate is a way to define different templates for different data structures. All the objects in Stack has same template however heap objects requires some attention. For every heap data structure a data template is defined. HeapFrameItemTemplateSelector
decides which data structure will be displayed in which way.
Object Graph Library Demo is action
Using Library
A working demo project is added with the project. To embed it in your project, first you have to add reference to "ObjectGraphLibray" project. Where you want to to render add a ContentPresenter their and name it as "GraphPresenter". Open C# file and first include add below code on the top of file
using ObjectGraphLibrary;
using ObjectGraphLibrary.ObjectModel;
using ObjectGraphLibrary.UI.Xaml;
Add this code where you actually want to load the user interface. It can be in constructor, load event handler or button click handler etc.
ObservableStack stack;
ObservableHeap heap;
JsonConverter.Deserialize(jsonText, out stack, out heap);
var graph = new ObjectGraphPresenter { Stack= stack, Heap = heap };
GraphPresenter.Content = graph;
Where "jsonText" is the json string in the format as explained below
Json Format
Json root object contains two keys Stack and Heap. Type of Stack is array and each item in Stack array will represent a Stack Frame.Each Stack Frame has two keys Label and Items. Label is the Header show on Stack Frame and Items is the array of variables in Stack Frame. Each variable in "Items" contains two field Label and Value. Label field on each variable is the name of variable and is show on left side in StackFrameItem. Value field of variable is complicated and is discussed at the end. Second key in Json root is "Heap" of type object that contains heap items against that particular heap item unique id represented as string. Value of heap item is same as stack frame variable value.
Stack Frame Variable Value and Heap Item Value both has same format. Any type of value is assigned to heap item value i.e number, Boolean, string, null, array, object. However stack frame variable value doesn't support array and object. To refer item in heap a special case-sensitive string of format "REF-XX" is used, where XX is the unique id of heap item
Sample Json
{
"Stack": [
{
"Label": "Globals",
"Items": [
{
"Label": "sample_list",
"Value": "REF-1"
},
{
"Label": "filter_marks",
"Value": "REF-2"
}
]
},
{
"Label": "filter_marks",
"Items": [
{
"Label": "lst",
"Value": "REF-1"
},
{
"Label": "integers",
"Value": "REF-3"
},
{
"Label": "strings",
"Value": "REF-4"
},
{
"Label": "element",
"Value": "Huzaifah"
}
]
}
],
"Heap": {
"1": [
25,
"Huzaifah",
38,
"Adnan",
54,
"Abdul Rehman"
],
"2" : "filter_marks(lst)",
"3" : [
25
],
"4" : [
"Huzaifah"
]
}
}
Source Code and Demo Project
Download complete source code from here http://gallery.technet.microsoft.com/Object-Graph-Library-to-0d110ece/
It contains entire source code of ObjectGraphLibrary and a demo project to test the library. If you have any question feel free to comment below or contact me at u.adnan@outlook.com. Follow me @u.adnan