示例#1
0
        /* compute the tree and all the counters and write all that to the backing store */
        bool BuildTreeAndComputeStats()
        {
            /* id of the previous thread */
            int prevThreadId = -1;

            /* information about the current thread (to speed up lookup) */
            int prevDepth = 0;
            ArrayList stack = null;
            SortedList functions = null;
            ArrayList queuedNodes = null;

            Stream s = null;
            ProgressForm progressForm = null;

            const int prevStackInitialSize = 100;
            int prevStackMaxSize = prevStackInitialSize;
            int[] prevStackTrace = new int[prevStackInitialSize];
            int prevStackLen = 0;
            StacktraceTable stacktraceTable = logResult.callstackHistogram.readNewLog.stacktraceTable;

            //  Preprocessing for function filters
            int nIncludeCallFilters = 0;
            int nIncludeAllocFilters = 0;

            for (int j=0; j < filterInclude.Length; j++)
            {
                if (filterInclude[j].functionId != -1)
                {
                    if (filterInclude[j].nodetype == TreeNode.NodeType.Call)
                        nIncludeCallFilters++;
                    else if (filterInclude[j].nodetype == TreeNode.NodeType.Allocation)
                        nIncludeAllocFilters++;
                }
            }

            if (firstNewStack != -1)
            {
                stacktraceTable.FreeEntries( firstNewStack );
            }
            firstNewStack = -1;

            try
            {
                /* log parser code (straight from the ReadNewLog.cs) */
                s = new FileStream(logFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                r = new StreamReader(s);

                progressForm = new ProgressForm();
                progressForm.Text = "Preparing call tree view";
                progressForm.Visible = true;
                progressForm.setProgress(0);
                progressForm.TopMost = false;
                int maxProgress = (int)(r.BaseStream.Length/1024);
                progressForm.setMaximum(maxProgress);

                buffer = new byte[4096];
                bufPos = 0;
                bufLevel = 0;
                line = 1;
                StringBuilder sb = new StringBuilder();
                c = ReadChar();

                bool found;
                string assemblyName = null;
                int threadid = 0, stackid = 0;
                TreeNode.NodeType nodetype = TreeNode.NodeType.Call;

                while (c != -1)
                {
                    found = false;
                    if ((line % 1024) == 0)
                    {
                        int currentProgress = (int)(pos/1024);
                        if (currentProgress <= maxProgress)
                        {
                            progressForm.setProgress(currentProgress);
                            Application.DoEvents();
                        }
                    }
                    lastLineStartPos = pos-1;

                    /* only parse calls and allocations */
                    switch (c)
                    {
                        case -1:
                            break;

                            // 'A' with thread identifier
                        case '!':
                        {
                            found = true;
                            c = ReadChar();
                            threadid = ReadInt();
                            ReadInt();
                            stackid = ReadInt();
                            nodetype = TreeNode.NodeType.Allocation;
                            if (c == -1)    {found = false;}
                            break;
                        }

                        case 'C':
                        case 'c':
                        {
                            found = true;
                            c = ReadChar();
                            nodetype = TreeNode.NodeType.Call;
                            threadid = ReadInt();
                            stackid = ReadInt();
                            if (c == -1)    {found = false;}
                            break;
                        }

                        case 'y':
                        case 'Y':
                        {
                            found = true;
                            c = ReadChar();
                            nodetype = TreeNode.NodeType.AssemblyLoad;
                            threadid = ReadInt();
                            /* int assemblyId = */ ReadInt();

                            while (c == ' ' || c == '\t')
                            {
                                c = ReadChar();
                            }
                            sb.Length = 0;
                            while (c > ' ')
                            {
                                sb.Append((char)c);
                                c = ReadChar();
                            }
                            assemblyName = sb.ToString();
                            break;
                        }

                        default:
                        {
                            // just ignore the unknown
                            while(c != '\n' && c != '\r')
                            {
                                c = ReadChar();
                            }
                            break;
                        }
                    }
                    while (c == ' ' || c == '\t')
                        c = ReadChar();
                    if (c == '\r')
                        c = ReadChar();
                    if (c == '\n')
                    {
                        c = ReadChar();
                        line++;
                    }
                    if(!found)
                    {
                        continue;
                    }

                    int[] stacktrace = IndexToStacktrace(stackid);
                    bool fFoundCallInclude = true;
                    bool fFoundCallExclude = false;
                    bool fFoundAllocInclude = true;
                    bool fFoundAllocExclude = false;

                    int includeMatches;

                    //  Apply filters to current node
                    if (filterInclude.Length != 0 || filterExclude.Length != 0)
                    {
                        if (nodetype == TreeNode.NodeType.Call ||
                            nodetype == TreeNode.NodeType.Allocation)
                        {
                            int i = 0;
                            int includesFound = 0;
                            fFoundCallInclude = false;

                            if (nodetype == TreeNode.NodeType.Allocation)
                            {
                                i = 2;
                            }

                            for (; i < stacktrace.Length; i++)
                            {
                                includeMatches = 0;

                                //  See if the stack contain the required include functions
                                for (int j=0; j < filterInclude.Length; j++)
                                {
                                    if (filterInclude[j].nodetype == TreeNode.NodeType.Call && filterInclude[j].functionId != -1)
                                    {
                                        if (stacktrace[i] == filterInclude[j].functionId )
                                            includeMatches++;
                                    }

                                }

                                if (includeMatches > 0)
                                    includesFound++;

                                //  Now see if the stack contains any exclude functions
                                for (int j=0; j < filterExclude.Length; j++)
                                {
                                    if (filterExclude[j].nodetype == TreeNode.NodeType.Call &&
                                        stacktrace[i] == filterExclude[j].functionId )
                                    {
                                        //  Any exclusion match gets this node bounced
                                        fFoundCallExclude = true;
                                        break;
                                    }
                                }
                            }

                            //  This node can pass the filter only if all include filters are found
                            if (includesFound == nIncludeCallFilters)
                                fFoundCallInclude = true;
                        }
                        else
                        {
                            fFoundCallInclude = false;
                        }

                        if (nodetype == TreeNode.NodeType.Allocation)
                        {
                            includeMatches = 0;
                            fFoundAllocInclude = false;

                            //  See if the stack contain the required include allocations
                            for (int j=0; j < filterInclude.Length; j++)
                                if (filterInclude[j].nodetype == TreeNode.NodeType.Allocation)
                                {
                                    if (stacktrace[0] == filterInclude[j].functionId || filterInclude[j].functionId == -1)
                                        includeMatches++;
                                }

                            if (includeMatches > 0 || nIncludeAllocFilters == 0)
                                fFoundAllocInclude = true;

                            //  Now see if the stack contains any exclude allocations
                            for (int j=0; j < filterExclude.Length; j++)
                            {
                                if (filterExclude[j].nodetype == TreeNode.NodeType.Allocation &&
                                    stacktrace[0] == filterExclude[j].functionId)
                                {
                                    fFoundAllocExclude = true;
                                    break;
                                }
                            }
                        }
                    }

                    //  Proceed to process this node only if the trace has all functions
                    //  and no exclude functions.
                    if ( !fFoundCallInclude || fFoundCallExclude ||
                        !fFoundAllocInclude || fFoundAllocExclude)
                    {
                        //  Skip this node
                        continue;
                    }

                    /* if thread changed, have to retrieve information about it.
                     * info about the last thread is cached to speed up the process */
                    if(threadid != prevThreadId)
                    {
                        if(prevThreadId != -1)
                        {
                            /* store everything about the previous thread */
                            ThreadState prevState = threads[prevThreadId];
                            prevState.prevStackLen = prevStackLen;
                            prevState.prevStackTrace = prevStackTrace;
                            prevState.functions = functions;
                            prevState.prevDepth = prevDepth;
                            prevState.stack = stack;
                            prevState.queuedNodes = queuedNodes;
                        }
                        else
                        {
                            /* this is the first call ever, mark the
                             * thread where it occured as the main thread */
                            firstThread = threadid;
                        }

                        /* get the information about the current (new) thread */
                        ThreadState state;
                        if (!threads.TryGetValue(threadid, out state))
                        {
                            /* create if necessary */
                            state = new ThreadState();
                            state.prevStackLen = 0;
                            state.prevStackTrace = new int[prevStackInitialSize];
                            state.prevDepth = 0;
                            state.stack = new ArrayList();
                            state.functions = new SortedList();
                            state.queuedNodes = new ArrayList();

                            TreeNode threadRoot = new TreeNode(TreeNode.NodeType.Call, 0);
                            state.stack.Add(threadRoot);

                            threads[threadid] = state;
                        }

                        prevStackLen = state.prevStackLen;
                        prevStackTrace = state.prevStackTrace;
                        prevStackMaxSize = prevStackTrace.Length;

                        prevDepth = state.prevDepth;
                        stack = state.stack;
                        functions = state.functions;
                        queuedNodes = state.queuedNodes;
                        prevThreadId = threadid;
                    }

                    /* if we're here, `iscall`, `stackid`, and `threadid` are set correctly */
                    int depth = 0;

                    if ( nodetype == TreeNode.NodeType.Allocation )
                    {
                        //  To build a call tree from the allocation log
                        //  Need to recreate the stacks and Call nodes that got us here.

                        //  Ignore first 2 ints in the stack trace.  They are allocation information.
                        int curStackLen = stacktrace.Length - 2;
                        int i;
                        bool fNewStack;

                        //  Find out how much of the callstack we need to construct
                        fNewStack = curStackLen != prevStackLen;
                        for (i = 0; i < curStackLen && i < prevStackLen; i++)
                        {
                            if (prevStackTrace[i] != stacktrace[i+2])
                            {
                                fNewStack = true;
                                break;
                            }
                        }

                        int nextStackIndex = stacktraceTable.Length;
                        for ( ; i < curStackLen; i++)
                        {
                            // We blindly add a new entry to the stack table, even though this stack may already
                            // exist.   Searching for a match would be expensive, so for now just do a new allocation.
                            // If this becomes hugely expensive, it will be worth making the stack trace searchable.
                            stacktraceTable.Add( nextStackIndex, stacktrace, 2, i+1, false);
                            TreeNode callnode = new TreeNode(TreeNode.NodeType.Call, nextStackIndex);
                            callnode.nodeOffset = lastLineStartPos;
                            queuedNodes.Add( callnode );

                            if (firstNewStack == -1)
                            {
                                //  Remember which stacks we created
                                firstNewStack = nextStackIndex;
                            }

                            nextStackIndex++;
                        }

                        if (fNewStack)
                        {
                            //  Reallocate prev stack if neccessary
                            if (curStackLen > prevStackMaxSize)
                            {
                                prevStackMaxSize += prevStackInitialSize;
                                prevStackTrace = new int[prevStackMaxSize];
                            }

                            //  Save a copy of the current stack
                            for (i = 0; i < curStackLen; i++)
                            {

                                prevStackTrace[i] = stacktrace[i+2];
                            }
                            prevStackLen = curStackLen;
                        }
                    }
                    else if ( nodetype == TreeNode.NodeType.Call )
                    {
                        //  Reallocate prev stack if neccessary
                        if (stacktrace.Length > prevStackMaxSize)
                        {
                            prevStackMaxSize += prevStackInitialSize;
                            prevStackTrace = new int[prevStackMaxSize];
                        }
                        prevStackLen = stacktrace.Length;
                        stacktrace.CopyTo( prevStackTrace, 0 );
                    }

                    TreeNode node = new TreeNode(nodetype, stackid);
                    int functionId = (nodetype != TreeNode.NodeType.AssemblyLoad ? stacktrace[stacktrace.Length - 1] : 0);

                    switch(nodetype)
                    {
                        case TreeNode.NodeType.Allocation:
                            node.data.bytesAllocated = stacktrace[1];
                            break;

                        case TreeNode.NodeType.Call:
                            if(functionId == 0)
                            {
                                node.isunmanaged = true;
                            }
                            break;

                        case TreeNode.NodeType.AssemblyLoad:
                            if(!assemblyNameToIdMap.Contains(assemblyName))
                            {
                                assemblyNameToIdMap.Add(assemblyName, null);
                                node.nameId = assemblyNames.Add(assemblyName);

                                queuedNodes.Add(node);
                            }
                            continue;
                    }

                    queuedNodes.Add(node);
                    for(int i = 0; i < queuedNodes.Count; i++)
                    {
                        node = (TreeNode)queuedNodes[i];
                        nodetype = node.nodetype;
                        stacktrace = IndexToStacktrace(node.stackid);
                        int stackLength = stacktrace.Length;

                        if(nodetype == TreeNode.NodeType.Allocation)
                        {
                            //  Skip first 2 entries in the stack.  They are type-id and bytes-allocated.
                            //  Add 1 to depth so allocation looks like a call to allocation function.
                            depth = stackLength - 2 + 1;
                        }
                        else if(nodetype == TreeNode.NodeType.Call)
                        {
                            depth = stackLength;
                        }
                        else if(nodetype == TreeNode.NodeType.AssemblyLoad)
                        {
                            depth = stackLength;
                        }
                        if(depth <= 0)
                        {
                            continue;
                        }

                        if(depth > prevDepth)
                        {
                            /* kids go to the stack */
                            if(depth - prevDepth > 1)
                            {
                                for(int idx = 1; idx < depth; idx++)
                                {
                                    TreeNode n = new TreeNode(TreeNode.NodeType.Call, -idx);
                                    n.nodeOffset = lastLineStartPos;
                                    stack.Add(n);
                                }
                            }
                            stack.Add(node);
                        }
                        else
                        {
                            /* moving up or sideways, have to adjust the stats
                            * and dump some of the branches to the backing store */
                            for(int j = 1 + prevDepth; j-- > depth + 1;)
                            {
                                if(((TreeNode)stack[j]).nodetype == TreeNode.NodeType.Call)
                                {
                                    /* record functions left */
                                    LeaveFunction(functions, GetFunctionIdFromStackId(((TreeNode)stack[j]).stackid));
                                }
                                UpdateStats(stack[j - 1], stack[j]);
                                ((TreeNode)stack[j - 1]).kidOffset = Dump(stack[j]);
                            }
                            if(((TreeNode)stack[depth]).nodetype == TreeNode.NodeType.Call)
                            {
                                LeaveFunction(functions, GetFunctionIdFromStackId(((TreeNode)stack[depth]).stackid));
                            }
                            UpdateStats(stack[depth - 1], stack[depth]);
                            node.prevOffset = Dump(stack[depth]);
                            stack[depth] = node;
                            stack.RemoveRange(1 + depth, stack.Count - depth - 1);
                        }

                        /* adjust the global statistics */
                        if(nodetype == TreeNode.NodeType.Call)
                        {
                            functionId = stacktrace[stacktrace.Length - 1];
                            globalCallStats[functionId].timesCalled++;
                            foreach(int fid in functions.Keys)
                            {
                                globalCallStats[fid].totalFunctionsCalled++;
                            }

                            if(!globalCallStats[functionId].calledAlready)
                            {
                                globalCallStats[functionId].calledAlready = true;
                                node.data.firstTimeBroughtIn = true;
                                foreach(TreeNode n in stack)
                                {
                                    n.data.numberOfNewFunctionsBroughtIn++;
                                }
                                /* `node` (the new function itself) is on the
                                * stack too, so we have to reverse its counter */
                                node.data.numberOfNewFunctionsBroughtIn--;

                                foreach(int fid in functions.Keys)
                                {
                                    globalCallStats[fid].totalNewFunctionsBroughtIn++;
                                }
                            }

                            /* record entering the function */
                            EnterFunction(functions, functionId);
                        }
                        else if(nodetype == TreeNode.NodeType.Allocation)
                        {
                            foreach(int fid in functions.Keys)
                            {
                                globalCallStats[fid].totalBytesAllocated += stacktrace[1];
                            }
                            globalAllocStats[stacktrace[0]].timesAllocated++;
                            globalAllocStats[stacktrace[0]].totalBytesAllocated += stacktrace[1];
                        }

                        prevDepth = depth;
                    }
                    queuedNodes.Clear();
                }
            }
            catch
            {
                /* exceptions are no good */
                MessageBox.Show(this, "Error creating backing store file, check if there is\nenough space on drive that holds your TEMP directory", "Failure");
                return false;
                // throw new Exception(e.Message + "\n" + e.StackTrace);
            }
            finally
            {
                /* get rid of the progress form and close the log file */
                if(progressForm != null)
                {
                    progressForm.Visible = false;
                    progressForm.Dispose();
                }
                if(s != null)
                {
                    s.Close();
                }
            }

            /* dump the root and the remains of the tree
             * that are still in memory to the backing store */
            foreach(ThreadState state in threads.Values)
            {
                stack = state.stack;
                for(int j = stack.Count; j-- > 1;)
                {
                    LeaveFunction(functions, GetFunctionIdFromStackId(((TreeNode)stack[j]).stackid));
                    UpdateStats(stack[j - 1], stack[j]);
                    ((TreeNode)stack[j - 1]).kidOffset = Dump(stack[j]);
                }
                ((TreeNode)stack[0]).HasKids = true;
                stack.RemoveRange(1, stack.Count - 1);
            }

            /* remove spurious threads from the thread array. don't think
             * it's an issue anymore but the code doesn't do anybody no harm */
            List<int> nulls = new List<int>();
            foreach(int key in threads.Keys)
            {
                if (threads[key] == null)
                {
                    nulls.Add(key);
                }
            }
            foreach(int key in nulls)
            {
                threads.Remove(key);
            }

            writer.Flush();
            return true;
        }
示例#2
0
        internal void ReadFile(long startFileOffset, long endFileOffset, ReadLogResult readLogResult)
        {
            ProgressForm progressForm = new ProgressForm();
            progressForm.Text = string.Format("Progress loading {0}", fileName);
            progressForm.Visible = progressFormVisible;
            progressForm.setProgress(0);
            if (stacktraceTable == null)
                stacktraceTable = new StacktraceTable();
            if (timePos == null)
                timePos = new TimePos[1000];
            AddTypeName(0, "Free Space");
            try
            {
                Stream s = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                r = new StreamReader(s);
                for (timePosIndex = timePosCount; timePosIndex > 0; timePosIndex--)
                    if (timePos[timePosIndex-1].pos <= startFileOffset)
                        break;
                // start at the beginning if no later start point available or asked for info that can only
                // be constructed by reading the whole file.
                if (timePosIndex <= 1 || readLogResult.relocatedHistogram != null || readLogResult.finalizerHistogram != null
                                      || readLogResult.criticalFinalizerHistogram != null || readLogResult.liveObjectTable != null)
                {
                    pos = 0;
                    timePosIndex = 1;
                }
                else
                {
                    timePosIndex--;
                    pos = timePos[timePosIndex].pos;
                }
                if (timePosCount == 0)
                {
                    timePos[0] = new TimePos(0.0, 0);
                    timePosCount = timePosIndex = 1;
                }
                s.Position = pos;
                buffer = new byte[4096];
                bufPos = 0;
                bufLevel = 0;
                int maxProgress = (int)(r.BaseStream.Length/1024);
                progressForm.setMaximum(maxProgress);
                line = 1;
                StringBuilder sb = new StringBuilder();
                ulong[] ulongStack = new ulong[1000];
                int[] intStack = new int[1000];
                int stackPtr = 0;
                c = ReadChar();
                bool thisIsR = false, previousWasR;
                bool extendedRootInfoSeen = false;
                int lastTickIndex = 0;
                bool newGcEvent = false;

                while (c != -1)
                {
                    if (pos > endFileOffset)
                        break;
                    if ((line % 1024) == 0)
                    {
                        int currentProgress = (int)(pos/1024);
                        if (currentProgress <= maxProgress)
                        {
                            progressForm.setProgress(currentProgress);
                            Application.DoEvents();
                            if (progressForm.DialogResult == DialogResult.Cancel)
                                break;
                        }
                    }
                    lastLineStartPos = pos-1;
                    previousWasR = thisIsR;
                    thisIsR = false;
                    switch (c)
                    {
                        case    -1:
                            break;

                        case    'F':
                        case    'f':
                        {
                            c = ReadChar();
                            int funcIndex = ReadInt();
                            while (c == ' ' || c == '\t')
                                c = ReadChar();
                            sb.Length = 0;
                            // Name may contain spaces if they are in angle brackets.
                            // Example: <Module>::std_less<unsigned void>.()
                            // The name may be truncated at 255 chars by profilerOBJ.dll
                            int angleBracketsScope = 0;
                            while (c > ' ' || angleBracketsScope != 0 && sb.Length < 255)
                            {
                                if (c == '<')
                                    angleBracketsScope++;
								
                                sb.Append((char)c);
                                c = ReadChar();

                                if (c == '>' && angleBracketsScope > 0)
                                    angleBracketsScope--;
                            }
                            string name = sb.ToString();
                            while (c == ' ' || c == '\t')
                                c = ReadChar();
                            sb.Length = 0;
                            while (c > '\r')
                            {
                                sb.Append((char)c);
                                if (c == ')')
                                {
                                    c = ReadChar();
                                    break;
                                }
                                c = ReadChar();
                            }
                            string signature = sb.ToString();

                            ulong addr = ReadULong();
                            uint size = ReadUInt();
                            int modIndex = ReadInt();
                            int stackIndex = ReadInt();

                            if (c != -1)
                            {
                                EnsureStringCapacity(funcIndex, ref funcName);
                                funcName[funcIndex] = name;
                                EnsureStringCapacity(funcIndex, ref funcSignature);
                                funcSignature[funcIndex] = signature;
                                EnsureIntCapacity(funcIndex, ref funcModule);
                                funcModule[funcIndex] = modIndex;

                                string nameAndSignature = name;
                                if (signature != null)
                                    nameAndSignature = name + ' '+signature;

                                if (stackIndex >= 0 && readLogResult.functionList != null)
                                {
                                    funcSignatureIdHash[nameAndSignature] = funcIndex;
                                    readLogResult.functionList.Add(funcIndex, stackIndex, size, modIndex);
                                }
                            }
                            break;
                        }

                        case    'T':
                        case    't':
                        {
                            c = ReadChar();
                            int typeIndex = ReadInt();
                            while (c == ' ' || c == '\t')
                                c = ReadChar();
                            if (c != -1 && Char.IsDigit((char)c))
                            {
                                if (ReadInt() != 0)
                                {
                                    finalizableTypes[typeIndex] = true;
                                }
                            }
                            while (c == ' ' || c == '\t')
                                c = ReadChar();
                            sb.Length = 0;
                            while (c > '\r')
                            {
                                sb.Append((char)c);
                                c = ReadChar();
                            }
                            string typeName = sb.ToString();
                            if (c != -1)
                            {
                                AddTypeName(typeIndex, typeName);
                            }
                            break;
                        }

                        // 'A' with thread identifier
                        case    '!':
                        {
                            c = ReadChar();
                            int threadId = ReadInt();
                            ulong id = ReadULong();
                            int typeSizeStackTraceIndex = ReadInt();
                            typeSizeStackTraceIndex = stacktraceTable.MapTypeSizeStacktraceId(typeSizeStackTraceIndex);
                            if (c != -1)
                            {
                                if (readLogResult.liveObjectTable != null)
                                    readLogResult.liveObjectTable.InsertObject(id, typeSizeStackTraceIndex, lastTickIndex, lastTickIndex, true, readLogResult.sampleObjectTable);
                                if (pos >= startFileOffset && pos < endFileOffset && readLogResult.allocatedHistogram != null)
                                {
                                    // readLogResult.calls.Add(new CallOrAlloc(false, threadId, typeSizeStackTraceIndex));
                                    readLogResult.allocatedHistogram.AddObject(typeSizeStackTraceIndex, 1);
                                }
                                List<string> prev;
                                if (assembliesJustLoaded.TryGetValue(threadId, out prev) && prev.Count != 0)
                                {
                                    foreach(string assemblyName in prev)
                                    {
                                        assemblies[assemblyName] = -typeSizeStackTraceIndex;
                                    }
                                    prev.Clear();
                                }
                            }
                            readLogResult.hadAllocInfo = true;
                            readLogResult.hadCallInfo = true;
                            break;
                        }

                        case    'A':
                        case    'a':
                        {
                            c = ReadChar();
                            ulong id = ReadULong();
                            int typeSizeStackTraceIndex = ReadInt();
                            typeSizeStackTraceIndex = stacktraceTable.MapTypeSizeStacktraceId(typeSizeStackTraceIndex);
                            if (c != -1)
                            {
                                if (readLogResult.liveObjectTable != null)
                                    readLogResult.liveObjectTable.InsertObject(id, typeSizeStackTraceIndex, lastTickIndex, lastTickIndex, true, readLogResult.sampleObjectTable);
                                if (pos >= startFileOffset && pos < endFileOffset && readLogResult.allocatedHistogram != null)
                                {
                                    // readLogResult.calls.Add(new CallOrAlloc(false, typeSizeStackTraceIndex));
                                    readLogResult.allocatedHistogram.AddObject(typeSizeStackTraceIndex, 1);
                                }
                            }
                            readLogResult.hadAllocInfo = true;
                            readLogResult.hadCallInfo = true;
                            break;
                        }

                        case    'C':
                        case    'c':
                        {
                            c = ReadChar();
                            if (pos <  startFileOffset || pos >= endFileOffset)
                            {
                                while (c >= ' ')
                                    c = ReadChar();
                                break;
                            }
                            int threadIndex = ReadInt();
                            int stackTraceIndex = ReadInt();
                            stackTraceIndex = stacktraceTable.MapTypeSizeStacktraceId(stackTraceIndex);
                            if (c != -1)
                            {
                                if (readLogResult.callstackHistogram != null)
                                {
                                    readLogResult.callstackHistogram.AddObject(stackTraceIndex, 1);
                                }
                                List<string> prev;
                                if (assembliesJustLoaded.TryGetValue(threadIndex, out prev) && prev.Count != 0)
                                {
                                    foreach(string assemblyName in prev)
                                    {
                                        assemblies[assemblyName] = stackTraceIndex;
                                    }
                                    prev.Clear();
                                }
                            }
                            readLogResult.hadCallInfo = true;
                            break;
                        }

                        case    'E':
                        case    'e':
                        {
                            c = ReadChar();
                            extendedRootInfoSeen = true;
                            thisIsR = true;
                            if (pos <  startFileOffset || pos >= endFileOffset)
                            {
                                while (c >= ' ')
                                    c = ReadChar();
                                break;
                            }
                            if (!previousWasR)
                            {
                                heapDumpEventList.AddEvent(lastTickIndex, null);
                                if (readLogResult.objectGraph != null && !readLogResult.objectGraph.empty)
                                {
                                    readLogResult.objectGraph.BuildTypeGraph(new FilterForm());
                                    readLogResult.objectGraph.Neuter();
                                }
                                readLogResult.objectGraph = new ObjectGraph(this, lastTickIndex);
                                Histogram[] h = readLogResult.heapDumpHistograms;
                                if (h != null)
                                {
                                    readLogResult.heapDumpHistograms = new Histogram[h.Length+1];
                                    for (int i = 0; i < h.Length; i++)
                                        readLogResult.heapDumpHistograms[i] = h[i];
                                    readLogResult.heapDumpHistograms[h.Length] = new Histogram(this);
                                }
                            }
                            ulong objectID = ReadULong();
                            GcRootKind rootKind = (GcRootKind)ReadInt();
                            GcRootFlags rootFlags = (GcRootFlags)ReadInt();
                            ulong rootID = ReadULong();
                            ObjectGraph objectGraph = readLogResult.objectGraph;
                            if (c != -1 && objectID > 0 && objectGraph != null && (rootFlags & GcRootFlags.WeakRef) == 0)
                            {
                                string rootName;
                                switch (rootKind)
                                {
                                case    GcRootKind.Stack:      rootName = "Stack";        break;
                                case    GcRootKind.Finalizer:  rootName = "Finalizer";    break;
                                case    GcRootKind.Handle:     rootName = "Handle";       break;
                                default:                       rootName = "Other";        break;                      
                                }

                                if ((rootFlags & GcRootFlags.Pinning) != 0)
                                    rootName += ", Pinning";
                                if ((rootFlags & GcRootFlags.WeakRef) != 0)
                                    rootName += ", WeakRef";
                                if ((rootFlags & GcRootFlags.Interior) != 0)
                                    rootName += ", Interior";
                                if ((rootFlags & GcRootFlags.Refcounted) != 0)
                                    rootName += ", RefCounted";

                                int rootTypeId = objectGraph.GetOrCreateGcType(rootName);
                                ulongStack[0] = objectID;
                                ObjectGraph.GcObject rootObject = objectGraph.CreateObject(rootTypeId, 1, ulongStack);

                                objectGraph.AddRootObject(rootObject, rootID);
                            }
                            break;
                        }
                            
                        case    'R':
                        case    'r':
                        {
                            c = ReadChar();
                            thisIsR = true;
                            if (extendedRootInfoSeen || pos <  startFileOffset || pos >= endFileOffset)
                            {
                                while (c >= ' ')
                                    c = ReadChar();
                                break;
                            }
                            if (!previousWasR)
                            {
                                heapDumpEventList.AddEvent(lastTickIndex, null);
                                if (readLogResult.objectGraph != null && !readLogResult.objectGraph.empty)
                                {
                                    readLogResult.objectGraph.BuildTypeGraph(new FilterForm());
                                    readLogResult.objectGraph.Neuter();
                                }
                                readLogResult.objectGraph = new ObjectGraph(this, lastTickIndex);
                                Histogram[] h = readLogResult.heapDumpHistograms;
                                if (h != null)
                                {
                                    readLogResult.heapDumpHistograms = new Histogram[h.Length+1];
                                    for (int i = 0; i < h.Length; i++)
                                        readLogResult.heapDumpHistograms[i] = h[i];
                                    readLogResult.heapDumpHistograms[h.Length] = new Histogram(this);
                                }
                            }
                            stackPtr = 0;
                            ulong objectID;
                            while ((objectID = ReadULong()) != ulong.MaxValue)
                            {
                                if (objectID > 0)
                                {
                                    ulongStack[stackPtr] = objectID;
                                    stackPtr++;
                                    if (stackPtr >= ulongStack.Length)
                                        ulongStack = GrowULongVector(ulongStack);
                                }
                            }
                            if (c != -1)
                            {
                                if (readLogResult.objectGraph != null)
                                    readLogResult.objectGraph.AddRoots(stackPtr, ulongStack);
                            }
                            break;
                        }

                        case    'O':
                        case    'o':
                        {
                            c = ReadChar();
                            if (pos <  startFileOffset || pos >= endFileOffset || readLogResult.objectGraph == null)
                            {
                                while (c >= ' ')
                                    c = ReadChar();
                                break;
                            }
                            ulong objectId = ReadULong();
                            int typeIndex = ReadInt();
                            uint size = ReadUInt();
                            stackPtr = 0;
                            ulong objectID;
                            while ((objectID = ReadULong()) != ulong.MaxValue)
                            {
                                if (objectID > 0)
                                {
                                    ulongStack[stackPtr] = objectID;
                                    stackPtr++;
                                    if (stackPtr >= ulongStack.Length)
                                        ulongStack = GrowULongVector(ulongStack);
                                }
                            }
                            if (c != -1)
                            {
                                ObjectGraph objectGraph = readLogResult.objectGraph;
                                objectGraph.GetOrCreateGcType(typeIndex);

                                int typeSizeStackTraceId = -1;
                                int allocTickIndex = 0;
                                // try to find the allocation stack trace and allocation time
                                // from the live object table
                                if (readLogResult.liveObjectTable != null)
                                {
                                    LiveObjectTable.LiveObject liveObject;
                                    readLogResult.liveObjectTable.GetNextObject(objectId, objectId, out liveObject);
                                    if (liveObject.id == objectId)
                                    {
                                        typeSizeStackTraceId = liveObject.typeSizeStacktraceIndex;
                                        allocTickIndex = liveObject.allocTickIndex;
                                        Histogram[] h = readLogResult.heapDumpHistograms;
                                        if (h != null)
                                            h[h.Length-1].AddObject(liveObject.typeSizeStacktraceIndex, 1);
                                    }
                                }
                                if (typeSizeStackTraceId == -1)
                                    typeSizeStackTraceId = stacktraceTable.GetOrCreateTypeSizeId(typeIndex, (int)size);
                                ObjectGraph.GcObject gcObject = objectGraph.CreateAndEnterObject(objectId, typeSizeStackTraceId, stackPtr, ulongStack);
                                gcObject.AllocTickIndex = allocTickIndex;
                            }
                            break;
                        }

                        case    'M':
                        case    'm':
                        {
                            c = ReadChar();
                            int modIndex = ReadInt();
                            sb.Length = 0;
                            while (c > '\r')
                            {
                                sb.Append((char)c);
                                c = ReadChar();
                            }
                            if (c != -1)
                            {
                                string lineString = sb.ToString();
                                int addrPos = lineString.LastIndexOf(" 0x");
                                if (addrPos <= 0)
                                    addrPos = lineString.Length;
                                int backSlashPos = lineString.LastIndexOf(@"\");
                                if (backSlashPos <= 0)
                                    backSlashPos = -1;
                                string basicName = lineString.Substring(backSlashPos + 1, addrPos - backSlashPos - 1);
                                string fullName = lineString.Substring(0, addrPos);

                                EnsureStringCapacity(modIndex, ref modBasicName);
                                modBasicName[modIndex] = basicName;
                                EnsureStringCapacity(modIndex, ref modFullName);
                                modFullName[modIndex] = fullName;
                            }
                            break;
                        }

                        case    'U':
                        case    'u':
                        {
                            c = ReadChar();
                            ulong oldId = ReadULong();
                            ulong newId = ReadULong();
                            uint length = ReadUInt();
                            Histogram reloHist = null;
                            if (pos >= startFileOffset && pos < endFileOffset)
                                reloHist = readLogResult.relocatedHistogram;
                            if (readLogResult.liveObjectTable != null)
                                readLogResult.liveObjectTable.UpdateObjects(reloHist, oldId, newId, length, lastTickIndex, readLogResult.sampleObjectTable);
                            break;
                        }

                        case    'V':
                        case    'v':
                        {
                            c = ReadChar();
                            ulong startId = ReadULong();
                            uint length = ReadUInt();
                            Histogram reloHist = null;
                            if (pos >= startFileOffset && pos < endFileOffset)
                                reloHist = readLogResult.relocatedHistogram;
                            if (readLogResult.liveObjectTable != null)
                                readLogResult.liveObjectTable.UpdateObjects(reloHist, startId, startId, length, lastTickIndex, readLogResult.sampleObjectTable);
                            break;
                        }

                        case    'B':
                        case    'b':
                            c = ReadChar();
                            int startGC = ReadInt();
                            int induced = ReadInt();
                            int condemnedGeneration = ReadInt();
                            if (startGC != 0)
                                newGcEvent = gcEventList.AddEvent(lastTickIndex, null);
                            if (newGcEvent)
                            {
                                if (startGC != 0)
                                {
                                    if (induced != 0)
                                    {
                                        for (int gen = 0; gen <= condemnedGeneration; gen++)
                                            inducedGcCount[gen]++;
                                    }
                                }
                                else
                                {
                                    int condemnedLimit = condemnedGeneration;
                                    if (condemnedLimit == 2)
                                        condemnedLimit = 3;
                                    for (int gen = 0; gen <= condemnedLimit; gen++)
                                    {
                                        cumulativeGenerationSize[gen] += generationSize[gen];
                                        gcCount[gen]++;
                                    }
                                }
                            }

                            for (int gen = 0; gen <= 3; gen++)
                                generationSize[gen] = 0;

                            while (c >= ' ')
                            {
                                ulong rangeStart = ReadULong();
                                ulong rangeLength = ReadULong();
                                ulong rangeLengthReserved = ReadULong();
                                int rangeGeneration = ReadInt();
                                if (c == -1 || rangeGeneration < 0)
                                    break;
                                if (readLogResult.liveObjectTable != null)
                                {
                                    if (startGC != 0)
                                    {
                                        if (rangeGeneration > condemnedGeneration && condemnedGeneration != 2)
                                            readLogResult.liveObjectTable.Preserve(rangeStart, rangeLength, lastTickIndex);
                                    }
                                    else
                                    {
                                        readLogResult.liveObjectTable.GenerationInterval(rangeStart, rangeLength, rangeGeneration, lastTickIndex);
                                    }
                                }
                                generationSize[rangeGeneration] += rangeLength;
                            }
                            if (startGC == 0 && readLogResult.liveObjectTable != null)
                            {
                                readLogResult.liveObjectTable.RecordGc(lastTickIndex, condemnedGeneration, readLogResult.sampleObjectTable, false);
                            }
                            break;

                        case    'L':
                        case    'l':
                        {
                            c = ReadChar();
                            int isCritical = ReadInt();
                            ulong objectId = ReadULong();
                            if (pos >= startFileOffset && pos < endFileOffset && readLogResult.liveObjectTable != null)
                            {
                                // try to find the allocation stack trace and allocation time
                                // from the live object table
                                LiveObjectTable.LiveObject liveObject;
                                readLogResult.liveObjectTable.GetNextObject(objectId, objectId, out liveObject);
                                if (liveObject.id == objectId)
                                {
                                    if (isCritical != 0 && readLogResult.criticalFinalizerHistogram != null)
                                        readLogResult.criticalFinalizerHistogram.AddObject(liveObject.typeSizeStacktraceIndex, 1);
                                    if (readLogResult.finalizerHistogram != null)
                                        readLogResult.finalizerHistogram.AddObject(liveObject.typeSizeStacktraceIndex, 1);
                                }
                            }
                            break;
                        }

                        case    'I':
                        case    'i':
                            c = ReadChar();
                            int tickCount = ReadInt();
                            if (c != -1)
                            {
                                lastTickIndex = AddTimePos(tickCount, lastLineStartPos);
                                if (maxTickIndex < lastTickIndex)
                                    maxTickIndex = lastTickIndex;
                            }
                            break;

                        case    'G':
                        case    'g':
                            c = ReadChar();
                            int gcGen0Count = ReadInt();
                            int gcGen1Count = ReadInt();
                            int gcGen2Count = ReadInt();
                            // if the newer 'b' lines occur, disregard the 'g' lines.
                            if (gcCount[0] == 0 && readLogResult.liveObjectTable != null)
                            {
                                if (c == -1 || gcGen0Count < 0)
                                    readLogResult.liveObjectTable.RecordGc(lastTickIndex, 0, readLogResult.sampleObjectTable, gcGen0Count < 0);
                                else
                                    readLogResult.liveObjectTable.RecordGc(lastTickIndex, gcGen0Count, gcGen1Count, gcGen2Count, readLogResult.sampleObjectTable);
                            }
                            break;

                        case    'N':
                        case    'n':
                        {
                            c = ReadChar();
                            int funcIndex;
                            int stackTraceIndex = ReadInt();
                            stackPtr = 0;

                            int flag = ReadInt();
                            int matched = flag / 4;
                            int hadTypeId = (flag & 2);
                            bool hasTypeId = (flag & 1) == 1;

                            if (hasTypeId)
                            {
                                intStack[stackPtr++] = ReadInt();
                                intStack[stackPtr++] = ReadInt();
                            }

                            if (matched > 0 && c != -1)
                            {
                                /* use some other stack trace as a reference */
                                int otherStackTraceId = ReadInt();
                                otherStackTraceId = stacktraceTable.MapTypeSizeStacktraceId(otherStackTraceId);
                                int[] stacktrace = stacktraceTable.IndexToStacktrace(otherStackTraceId);
                                if (matched > stacktrace.Length - hadTypeId)
                                    matched = stacktrace.Length - hadTypeId;
                                for(int i = 0; i < matched; i++)
                                {
                                    int funcId = stacktrace[i + hadTypeId];
                                    Debug.Assert(funcId < funcName.Length && funcName[funcId] != null);
                                    intStack[stackPtr++] = funcId;
                                    if (stackPtr >= intStack.Length)
                                    {
                                        intStack = GrowIntVector(intStack);
                                    }
                                }
                            }

                            while ((funcIndex = ReadInt()) >= 0)
                            {
                                intStack[stackPtr] = funcIndex;
                                stackPtr++;
                                if (stackPtr >= intStack.Length)
                                    intStack = GrowIntVector(intStack);
                            }

                            if (c != -1)
                            {
                                stacktraceTable.Add(stackTraceIndex, intStack, stackPtr, hasTypeId);
                            }
                            break;
                        }

                        case 'y':
                        case 'Y':
                        {
                            c = ReadChar();
                            int threadid = ReadInt();
                            if(!assembliesJustLoaded.ContainsKey(threadid))
                            {
                                assembliesJustLoaded[threadid] = new List<string>();
                            }
                            /* int assemblyId = */ ReadInt();

                            while (c == ' ' || c == '\t')
                            {
                                c = ReadChar();
                            }
                            sb.Length = 0;
                            while (c > '\r')
                            {
                                sb.Append((char)c);
                                c = ReadChar();
                            }
                            string assemblyName = sb.ToString();
                            assembliesJustLoaded[threadid].Add(assemblyName);
                            break;
                        }

                        case 'S':
                        case 's':
                        {
                            c = ReadChar();
                            int stackTraceIndex = ReadInt();
                            int funcIndex;
                            stackPtr = 0;
                            while ((funcIndex = ReadInt()) >= 0)
                            {
                                intStack[stackPtr] = funcIndex;
                                stackPtr++;
                                if (stackPtr >= intStack.Length)
                                    intStack = GrowIntVector(intStack);
                            }
                            if (c != -1)
                            {
                                stacktraceTable.Add(stackTraceIndex, intStack, stackPtr, false);
                            }
                            break;
                        }

                        case    'Z':
                        case    'z':
                        {
                            sb.Length = 0;
                            c = ReadChar();
                            while (c == ' ' || c == '\t')
                                c = ReadChar();
                            while (c > '\r')
                            {
                                sb.Append((char)c);
                                c = ReadChar();
                            }
                            if (c != -1)
                            {
                                lastTickIndex = AddTimePos(lastLineStartPos);
                                if (maxTickIndex < lastTickIndex)
                                    maxTickIndex = lastTickIndex;
                                commentEventList.AddEvent(lastTickIndex, sb.ToString());
                            }
                            break;
                        }

                        case    'H':
                        case    'h':
                        {
                            c = ReadChar();
                            int threadId = ReadInt();
                            ulong handleId = ReadULong();
                            ulong initialObjectId = ReadULong();
                            int stacktraceId = ReadInt();
                            if (c != -1)
                            {
                                if (readLogResult.handleHash != null)
                                    readLogResult.handleHash[handleId] = new HandleInfo(threadId, handleId, initialObjectId, lastTickIndex, stacktraceId);
                                if (readLogResult.createdHandlesHistogram != null)
                                    readLogResult.createdHandlesHistogram.AddObject(stacktraceId, 1);
                            }
                            break;
                        }

                        case    'J':
                        case    'j':
                        {
                            c = ReadChar();
                            int threadId = ReadInt();
                            ulong handleId = ReadULong();
                            int stacktraceId = ReadInt();
                            if (c != -1)
                            {
                                if (readLogResult.handleHash != null)         
                                {
                                    if (readLogResult.handleHash.ContainsKey(handleId))
                                        readLogResult.handleHash.Remove(handleId);
                                    else
                                    {
//                                        Console.WriteLine("Non-existent handle {0:x} destroyed in line {1}", handleId, line);
                                        int[] stacktrace = stacktraceTable.IndexToStacktrace(stacktraceId);
                                        for (int i = stacktrace.Length; --i >= 0; )
                                        {
                                            Console.WriteLine("  {0}", funcName[stacktrace[i]]);
                                        }
                                    }
                                }
                                if (readLogResult.destroyedHandlesHistogram != null)
                                    readLogResult.destroyedHandlesHistogram.AddObject(stacktraceId, 1);
                            }
                            break;
                        }
                        
                        default:
                        {
                            // just ignore the unknown
                            while(c != '\n' && c != '\r')
                            {
                                c = ReadChar();
                            }
                            break;
                        }
                    }
                    while (c == ' ' || c == '\t')
                        c = ReadChar();
                    if (c == '\r')
                        c = ReadChar();
                    if (c == '\n')
                    {
                        c = ReadChar();
                        line++;
                    }
                }
//                readLogResult.functionList.ReportCallCountSizes(readLogResult.callstackHistogram);
            }
//            catch (Exception)
//            {
//                throw new Exception(string.Format("Bad format in log file {0} line {1}", fileName, line));
//                throw;
//            }
            finally
            {
                progressForm.Visible = false;
                progressForm.Dispose();
                if (r != null)
                    r.Close();
            }
        }
		private void ReadFile(CallTreeForm callTrace, string fileName, Hashtable FuncExcl, Hashtable TypeExcl)
		{
			Hashtable funcCalled = new Hashtable();
			Hashtable TypeAlloc = new Hashtable();
			Stream s = null;
			ProgressForm progressForm = null;
			try
			{
				s = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
				r = new StreamReader(s);

				progressForm = new ProgressForm();
				progressForm.Text = "Preparing call tree view";
				progressForm.Visible = true;
				progressForm.setProgress(0);
				progressForm.TopMost = false;
				int maxProgress = (int)(r.BaseStream.Length/1024);
				progressForm.setMaximum(maxProgress);

				buffer = new byte[4096];
				bufPos = 0;
				bufLevel = 0;
				line = 1;
				StringBuilder sb = new StringBuilder();
				c = ReadChar();

				bool found;
				string assemblyName = null;
				int threadid = 0, stackid = 0;
				TreeNode.NodeType nodetype = TreeNode.NodeType.Call;

				while (c != -1)
				{
					found = false;
					if ((line % 1024) == 0)
					{
						int currentProgress = (int)(pos/1024);
						if (currentProgress <= maxProgress)
						{
							progressForm.setProgress(currentProgress);
						}
					}
					lastLineStartPos = pos-1;
					switch (c)
					{
						case    -1:
							break;
				
							// 'A' with thread identifier
						case    '!':
						{
							found = true;
							c = ReadChar();
							threadid = ReadInt();
							ReadInt();
							stackid = ReadInt();
							nodetype = TreeNode.NodeType.Allocation;
							if (c == -1)	{found = false;}
							break;
			
						}

						case    'C':
						case    'c':
						{
							found = true;
							c = ReadChar();
							nodetype = TreeNode.NodeType.Call;
							threadid = ReadInt();
							stackid = ReadInt();
							if (c == -1)	{found = false;}
							break;
						}

						
						case 'y':
						case 'Y':
						{
							found = true;
							c = ReadChar();
							nodetype = TreeNode.NodeType.AssemblyLoad;
							threadid = ReadInt();
							ReadInt();

							while (c == ' ' || c == '\t')
							{
								c = ReadChar();
							}
							sb.Length = 0;
							while (c > ' ')
							{
								sb.Append((char)c);
								c = ReadChar();
							}
							assemblyName = sb.ToString();
							break;
						}


						default:
						{
							// just ignore the unknown
							while(c != '\n' && c != '\r')
							{
								c = ReadChar();
							}
							break;
						}
					}
					while (c == ' ' || c == '\t')
						c = ReadChar();
					if (c == '\r')
						c = ReadChar();
					if (c == '\n')
					{
						c = ReadChar();
						line++;
					}
					if(!found)
					{
						continue;
					}
				
					string name = null;
					string typename = null;

					int[] stacktrace = callTrace.IndexToStacktrace(stackid);
					int functionId = (nodetype != TreeNode.NodeType.AssemblyLoad ? stacktrace[stacktrace.Length - 1] : 0);
					switch(nodetype)
					{
						case TreeNode.NodeType.Allocation:
							string key = null;
							if( (functionId < callTrace.LogResult.callstackHistogram.readNewLog.funcName.Length )&& 
								((name = callTrace.LogResult.callstackHistogram.readNewLog.funcName[functionId]) != null))
							{
								if( callTrace.LogResult.callstackHistogram.readNewLog.funcSignature[functionId] != null)
								{
									name += ' ' + callTrace.LogResult.callstackHistogram.readNewLog.funcSignature[functionId];
								}
							}
							else
							{
								name = "NATIVE FUNCTION ( UNKNOWN ARGUMENTS )";
							}
														
							// function Excl							
							if(FuncExcl.ContainsKey(name))
							{
								int alloc = (int)FuncExcl[(string)name];
								alloc += stacktrace[1];
								FuncExcl[name] = alloc;
							}
							else
							{
								FuncExcl.Add(name, stacktrace[1]);
							}
							
							// Type Excl
							if( stacktrace[0]>=0 && stacktrace[0] < callTrace.LogResult.callstackHistogram.readNewLog.typeName.Length)
							{
								typename = callTrace.LogResult.callstackHistogram.readNewLog.typeName[stacktrace[0]];
							}
							if(typename == null)
								typename = "NATIVE FUNCTION ( UNKNOWN ARGUMENTS )";
																											
							if(TypeExcl.ContainsKey(typename))
							{
								int alloc = (int)TypeExcl[(string)typename];
								alloc += stacktrace[1];
								TypeExcl[typename] = alloc;
							}
							else
							{
								TypeExcl.Add(typename, stacktrace[1]);
							}
							
							// Type Allocated by Excl
							if(name != "NATIVE FUNCTION ( UNKNOWN ARGUMENTS )")
								key = typename + '|' + functionId;
							else
								key = typename + '|' + 0;
							if( TypeAlloc.ContainsKey(key))
							{
								int alloc = (int)TypeAlloc[key];
								alloc += stacktrace[1];
								TypeAlloc[key] = alloc;
							}
							else
							{
								TypeAlloc.Add(key, stacktrace[1]);
							}
									
							break;
						case TreeNode.NodeType.Call:
							if(funcCalled.ContainsKey(functionId))
							{
								int calls = (int)funcCalled[functionId] + 1;;
								funcCalled[functionId]= calls;
							}
							else
							{
								funcCalled.Add(functionId,1);
							}
							break;
					}
				}

			}
			catch (Exception)
			{
				throw new Exception(string.Format("Bad format in log file {0} line {1}", fileName, line));
			}

			finally
			{
				progressForm.Visible = false;
				progressForm.Dispose();
				if (r != null)
					r.Close();
			}
		}