sysperfana/heapanalyser/Libraries/UI/HeapUiLib/Controls/HeapCellStatsControl.cs
author Jussi Ryoma <ext-jussi.s.ryoma@nokia.com>
Tue, 24 Aug 2010 14:01:48 +0300
changeset 16 72f198be1c1d
parent 8 15296fd0af4a
permissions -rw-r--r--
Crash Analyser Carbide Extension 1.4.0

/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
*   this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
*   this list of conditions and the following disclaimer in the documentation
*   and/or other materials provided with the distribution.
* - Neither the name of Nokia Corporation nor the names of its contributors
*   may be used to endorse or promote products derived from this software
*   without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/

using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using System.Text;
using SymbianUtils;
using HeapLib;
using HeapLib.Cells;
using HeapLib.Array;
using HeapLib.Reconstructor;
using HeapLib.Statistics;
using HeapLib.Statistics.Tracking.Base;
using HeapLib.Statistics.Tracking.BySymbol;
using HeapLib.Reconstructor.DataSources;

namespace HeapUiLib.Controls
{
    public partial class HeapCellStatsControl : UserControl
    {
        #region Constructors
        public HeapCellStatsControl()
        {
            InitializeComponent();
        }
        #endregion

        #region API
        #endregion

        #region Properties
        [Browsable(false)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public HeapReconstructor Reconstructor
        {
            get { return iReconstructor; }
            set
            {
                iReconstructor = value;
                //
                if ( iReconstructor != null )
                {
                    UpdateMainTable();
                    UpdateSummary();
                }
            }
        }

        private HeapStatistics Statistics
        {
            get
            {
                HeapStatistics ret = null;
                //
                if ( Reconstructor != null )
                {
                    ret = Reconstructor.Statistics;
                }
                //
                return ret;
            }
        }
        #endregion

        #region Event handlers
        private void iPG3_StatsTable_SelectionChanged( object sender, XPTable.Events.SelectionEventArgs e )
        {
            if ( e.NewSelectedIndicies.Length > 0 )
            {
                UpdateSelectionTotals();
            }
        }

        private void iPG3_StatsTable_PrepareForSort( object sender, XPTable.Events.SortEventArgs e )
        {
            TrackingComparisonBase type = null;
            switch ( e.Index )
            {
            default:
            case 0:
                type = new HeapLib.Statistics.Tracking.Base.TrackingInfoSortBySymbolName( false );
                break;
            case 1:
                type = new HeapLib.Statistics.Tracking.Base.TrackingInfoSortByCount( false );
                break;
            case 2:
                type = new HeapLib.Statistics.Tracking.Base.TrackingInfoSortByPayloadLength( false );
                break;
            case 3:
                type = new HeapLib.Statistics.Tracking.Base.TrackingInfoSortByAssociatedMemory( false );
                break;
            }
            //
            if ( type == null )
            {
                throw new Exception( "No comparer for specified column" );
            }
            //
            e.Comparer = new TrackingInfoComparerWrapper( type );
        }
        #endregion

        #region Internal classes
        private class TrackingInfoComparerWrapper : IComparer
        {
            #region Constructors
            public TrackingInfoComparerWrapper( TrackingComparisonBase aBase )
            {
                iBaseComparer = aBase;
            }
            #endregion

            #region IComparer Members
            public int Compare( object aLeft, object aRight )
            {
                TrackingInfo left = null;
                TrackingInfo right = null;
                //
                if ( ( aLeft is TrackingInfo ) && ( aRight is TrackingInfo ) )
                {
                    left = (TrackingInfo) aLeft;
                    right = (TrackingInfo) aRight;
                }
                else if ( aLeft is XPTable.Models.Cell && aRight is XPTable.Models.Cell )
                {
                    XPTable.Models.Cell cellLeft = ( aLeft as XPTable.Models.Cell );
                    XPTable.Models.Cell cellRight = ( aRight as XPTable.Models.Cell );
                    //
                    left = (TrackingInfo) cellLeft.Row.Tag;
                    right = (TrackingInfo) cellRight.Row.Tag;
                }

                // Now do the compare...
                int ret = iBaseComparer.Compare( left, right );
                return ret;
            }
            #endregion

            #region Data members
            private readonly TrackingComparisonBase iBaseComparer;
            #endregion
        }
        #endregion

        #region Internal methods
        private void UpdateMainTable()
        {
            iTable_SymbolMemory.BeginUpdate();
            iTable_SymbolMemory.TableModel.Rows.Clear();

            iReconstructor.Statistics.StatsAllocated.TrackerSymbols.SortByAllocatedMemory();
            //
            foreach ( TrackingInfo item in iReconstructor.Statistics.StatsAllocated.TrackerSymbols )
            {
                XPTable.Models.Row row = new XPTable.Models.Row();
                row.Tag = item;

                // SYMBOL
                System.Diagnostics.Debug.Assert( item.Symbol != null );
                row.Cells.Add( new XPTable.Models.Cell( item.Symbol.NameWithoutVTablePrefix ) );

                // ALLOC COUNT
                row.Cells.Add( new XPTable.Models.Cell( item.Count.ToString() ) );

                // MEMORY-PER-INSTANCE
                row.Cells.Add( new XPTable.Models.Cell( item.PayloadLength.ToString() ) );

                // TOTAL ALLOCATED MEMORY
                row.Cells.Add( new XPTable.Models.Cell( item.AssociatedMemory.ToString() ) );

                // Add row
                iTable_SymbolMemory.TableModel.Rows.Add( row );
            }

            iTable_SymbolMemory.EndUpdate();
        }

        private void UpdateSummary()
        {
            long heapCellHeaderOverheadSize = Statistics.SizeTotalHeader;
            long symbolicMatchMemorySize = Statistics.StatsAllocated.TrackerSymbols.TypeSize;
            long otherMemorySize = ( Statistics.StatsAllocated.TypeSize - Statistics.StatsAllocated.TrackerSymbols.TypeSize );
            long freeSpaceSize = Statistics.StatsFree.TypeSize;
            long totalCellCount = Statistics.StatsAllocated.TypeCount + Statistics.StatsFree.TypeCount;

            // 1ST GROUP
            iLV_Summary.Items[ 0 ].SubItems[ 1 ].Text = Statistics.StatsAllocated.TypeCount.ToString();
            iLV_Summary.Items[ 0 ].SubItems[ 2 ].Text = NumberFormattingUtils.NumberAsPercentageTwoDP( Statistics.StatsAllocated.TypeCount, totalCellCount ) + " %";
            iLV_Summary.Items[ 1 ].SubItems[ 1 ].Text = Statistics.StatsFree.TypeCount.ToString();
            iLV_Summary.Items[ 1 ].SubItems[ 2 ].Text = NumberFormattingUtils.NumberAsPercentageTwoDP( Statistics.StatsFree.TypeCount, totalCellCount ) + " %";
            
            // 2ND GROUP
            iLV_Summary.Items[ 2 ].SubItems[ 1 ].Text = symbolicMatchMemorySize.ToString();
            iLV_Summary.Items[ 2 ].SubItems[ 2 ].Text = NumberFormattingUtils.NumberAsPercentageTwoDP( symbolicMatchMemorySize, symbolicMatchMemorySize + otherMemorySize + freeSpaceSize ) + " %";
            iLV_Summary.Items[ 3 ].SubItems[ 1 ].Text = otherMemorySize.ToString();
            iLV_Summary.Items[ 3 ].SubItems[ 2 ].Text = NumberFormattingUtils.NumberAsPercentageTwoDP( otherMemorySize, symbolicMatchMemorySize + otherMemorySize + freeSpaceSize ) + " %";
            // (4) is a spacer
            iLV_Summary.Items[ 5 ].SubItems[ 1 ].Text = ( symbolicMatchMemorySize + otherMemorySize ).ToString();
            iLV_Summary.Items[ 5 ].SubItems[ 2 ].Text = NumberFormattingUtils.NumberAsPercentageTwoDP( symbolicMatchMemorySize + otherMemorySize, symbolicMatchMemorySize + otherMemorySize + freeSpaceSize ) + " %";
            iLV_Summary.Items[ 6 ].SubItems[ 1 ].Text = freeSpaceSize.ToString();
            iLV_Summary.Items[ 6 ].SubItems[ 2 ].Text = NumberFormattingUtils.NumberAsPercentageTwoDP( freeSpaceSize, symbolicMatchMemorySize + otherMemorySize + freeSpaceSize ) + " %";
            // (7) is a spacer
            iLV_Summary.Items[ 8 ].SubItems[ 1 ].Text = heapCellHeaderOverheadSize.ToString();
            iLV_Summary.Items[ 8 ].SubItems[ 2 ].Text = NumberFormattingUtils.NumberAsPercentageTwoDP( heapCellHeaderOverheadSize, symbolicMatchMemorySize + otherMemorySize + freeSpaceSize ) + " %";
            
            // 3RD GROUP
            iLV_Summary.Items[ 10 ].SubItems[ 1 ].Text = ( heapCellHeaderOverheadSize + symbolicMatchMemorySize + otherMemorySize ).ToString();
            iLV_Summary.Items[ 10 ].SubItems[ 2 ].Text = "100.00 %";
        }

        private void UpdateSelectionTotals()
        {
            bool atLeastOneValue = false;
            long total = 0;

            foreach ( XPTable.Models.Row row in iTable_SymbolMemory.SelectedItems )
            {
                TrackingInfo item = (TrackingInfo) row.Tag;
                //
                total += item.AssociatedMemory;
                atLeastOneValue = true;
            }

            string totalValueAsString = "[nothing selected]";
            string totalAsPercentageString = "";
            //
            if ( atLeastOneValue )
            {
                int allocCount;
                int freeCount;
                long freeSpaceSize;
                long allocatedUnknownSize;
                long allocatedSymbolMatchSize;
                long totalHeapAllocatedMemory = TotalAllocatedMemory( out allocCount, out freeCount, out freeSpaceSize, out allocatedUnknownSize, out allocatedSymbolMatchSize );
                //
                totalValueAsString = total.ToString();
                totalAsPercentageString = NumberFormattingUtils.NumberAsPercentageTwoDP( total, totalHeapAllocatedMemory ) + " %";
            }
            //
            iLV_Summary.Items[ 9 ].SubItems[ 1 ].Text = totalValueAsString;
            iLV_Summary.Items[ 9 ].SubItems[ 2 ].Text = totalAsPercentageString;
        }

        private long TotalAllocatedMemory( out int aAllocCount, out int aFreeCount, out long aFreeSpaceSize, out long aAllocatedUnknownSize, out long aAllocatedSymbolMatchSize )
        {
            aAllocCount = 0;
            aFreeCount = 0;
            aFreeSpaceSize = 0;
            aAllocatedUnknownSize = 0;
            aAllocatedSymbolMatchSize = 0;
            //
            HeapCellArray data = iReconstructor.Data;
            int count = data.Count;
            //
            for ( int i = 0; i < count; i++ )
            {
                HeapCell cell = data[ i ];
                //
                if ( cell.Type == HeapCell.TType.EAllocated )
                {
                    ++aAllocCount;
                    if ( cell.Symbol != null )
                        aAllocatedSymbolMatchSize += cell.Length;
                    else
                        aAllocatedUnknownSize += cell.Length;
                }
                else
                {
                    ++aFreeCount;
                    aFreeSpaceSize += cell.Length;
                }
            }

            return ( aAllocatedSymbolMatchSize + aAllocatedUnknownSize + aFreeSpaceSize );
        }
        #endregion

        #region Data members
        private HeapReconstructor iReconstructor = null;
        #endregion
    }
}