/// <summary> /// Create a stack source from 'graph'. samplingRatio is the ratio of size of the graph to /// the size of the actual heap (if you only sampled part of it). Counts are scaled by the /// inverse of this so that the expected size of the graph works out. /// /// log is were to send diagnostic messages (can be null) /// /// countMultipliers is an array (indexed by type Index), that will be used to multiply the /// counts in 'graph' when generating the stack source (thus if Type T has count 5 and /// countMultipliers[T] = 10 then the stack source will return 50. This is used to scale /// sampled graphs. /// </summary> public MemoryGraphStackSource(Graph graph, TextWriter log, float[] countMultipliers = null) { m_asMemoryGraph = graph as MemoryGraph; m_graph = graph; m_log = log; m_nodeStorage = graph.AllocNodeStorage(); m_childStorage = graph.AllocNodeStorage(); m_typeStorage = graph.AllocTypeNodeStorage(); m_sampleStorage = new StackSourceSample(this); m_countMultipliers = countMultipliers; // We need to reduce the graph to a tree. Each node is assigned a unique 'parent' which is its // parent in a spanning tree of the graph. // The +1 is for orphan node support. m_parent = new NodeIndex[(int)graph.NodeIndexLimit + 1]; // If it is a memory stack source (it pretty much always is), figure out the maximum address. // We use addresses as 'time' for stacks so that the 'when' field in perfView is meaningful. MemoryGraph asMemoryGraph = graph as MemoryGraph; if (asMemoryGraph != null) { for (NodeIndex idx = 0; idx < asMemoryGraph.NodeIndexLimit; idx++) { Address endAddress = asMemoryGraph.GetAddress(idx) + (uint)asMemoryGraph.GetNode(idx, m_nodeStorage).Size; if (m_maxAddress < endAddress) { m_maxAddress = endAddress; } } } }
private void VisitNodeFromSample(StackSourceSample sample) { MemoryNode currentNode = (MemoryNode)_OriginalMemoryGraph.GetNode((NodeIndex)sample.SampleIndex, _OriginalMemoryGraph.AllocNodeStorage()); VisitNode(currentNode); }