sysperfana/heapanalyser/Libraries/Engine/HeapComparisonLib/Data/ComparsionEngine.cs
changeset 8 15296fd0af4a
equal deleted inserted replaced
7:8e12a575a9b5 8:15296fd0af4a
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * Redistribution and use in source and binary forms, with or without
       
     6 * modification, are permitted provided that the following conditions are met:
       
     7 *
       
     8 * - Redistributions of source code must retain the above copyright notice,
       
     9 *   this list of conditions and the following disclaimer.
       
    10 * - Redistributions in binary form must reproduce the above copyright notice,
       
    11 *   this list of conditions and the following disclaimer in the documentation
       
    12 *   and/or other materials provided with the distribution.
       
    13 * - Neither the name of Nokia Corporation nor the names of its contributors
       
    14 *   may be used to endorse or promote products derived from this software
       
    15 *   without specific prior written permission.
       
    16 *
       
    17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
       
    18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
       
    21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       
    22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       
    23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       
    24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       
    25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       
    26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       
    27 * POSSIBILITY OF SUCH DAMAGE.
       
    28 * 
       
    29 * Initial Contributors:
       
    30 * Nokia Corporation - initial contribution.
       
    31 *
       
    32 * Contributors:
       
    33 *
       
    34 * Description: 
       
    35 *
       
    36 */
       
    37 
       
    38 using System;
       
    39 using System.Text;
       
    40 using System.Text.RegularExpressions;
       
    41 using System.Threading;
       
    42 using System.Collections;
       
    43 using System.Collections.Generic;
       
    44 using SymbianUtils;
       
    45 using SymbianUtils.Range;
       
    46 using SymbianUtils.RawItems;
       
    47 using HeapLib.Cells;
       
    48 using HeapLib.Array;
       
    49 using HeapLib.Reconstructor;
       
    50 using SymbianUtils.TextUtilities.Readers.Types.Array;
       
    51 
       
    52 namespace HeapComparisonLib.Data
       
    53 {
       
    54     public class ComparsionEngine : AsyncArrayReader<HeapCell>
       
    55     {
       
    56         #region Constructors & destructor
       
    57         public ComparsionEngine( HeapReconstructor aReconstructor1, HeapReconstructor aReconstructor2 )
       
    58             : base( new ComparsionCellSupplierProxy( aReconstructor1 ) )
       
    59         {
       
    60             iReconstructor1 = aReconstructor1;
       
    61             iReconstructor2 = aReconstructor2;
       
    62         }
       
    63         #endregion
       
    64 
       
    65         #region API
       
    66         public void Compare()
       
    67         {
       
    68             AsyncRead();
       
    69         }
       
    70         #endregion
       
    71 
       
    72         #region Properties
       
    73         public HeapReconstructor Reconstructor1
       
    74         {
       
    75             get { return iReconstructor1; }
       
    76         }
       
    77 
       
    78         public HeapReconstructor Reconstructor2
       
    79         {
       
    80             get { return iReconstructor2; }
       
    81         }
       
    82 
       
    83         public HeapCellArrayWithStatistics ResultsUnchanged
       
    84         {
       
    85             get { return iUnchanged; }
       
    86         }
       
    87 
       
    88         public HeapCellArrayWithStatistics ResultsUnchangedLengthButDifferentContents
       
    89         {
       
    90             get { return iUnchangedLengthButDifferentContents; }
       
    91         }
       
    92 
       
    93         public HeapCellArrayWithStatistics ResultsChanged
       
    94         {
       
    95             get { return iChanged; }
       
    96         }
       
    97 
       
    98         public HeapCellArrayWithStatistics ResultsUniqueInHeap1
       
    99         {
       
   100             get { return iUniqueInReconstructor1; }
       
   101         }
       
   102 
       
   103         public HeapCellArrayWithStatistics ResultsUniqueInHeap2
       
   104         {
       
   105             get { return iUniqueInReconstructor2; }
       
   106         }
       
   107         #endregion
       
   108 
       
   109         #region From AsyncArrayReader
       
   110         protected override void HandleObject( HeapCell aCell, int aIndex, int aCount )
       
   111         {
       
   112             if ( aCell.Address == 0xc8023e5c || 
       
   113                  aCell.Address == 0xc8024064 ||
       
   114                  aCell.Address == 0xc80276d4 ||
       
   115                  aCell.Address == 0xc82100b4
       
   116                 )
       
   117             {
       
   118                 int x = 0;
       
   119                 x++;
       
   120             }
       
   121 
       
   122             uint address = aCell.Address;
       
   123             HeapCell locatedCell = iReconstructor2.Data.CellByExactAddress( address );
       
   124             //
       
   125             if ( locatedCell != null )
       
   126             {
       
   127                 System.Diagnostics.Debug.Assert( aCell.Tag == null );
       
   128 
       
   129                 // Remove sucessfully located cells from the 2nd list
       
   130                 iReconstructor2.Data.Remove( locatedCell );
       
   131 
       
   132                 // Check vtables to detect if the same
       
   133                 HeapCell.TType origType = aCell.Type;
       
   134                 HeapCell.TType locatedType = locatedCell.Type;
       
   135 
       
   136                 uint origVTable = aCell.PossibleVTableAddress;
       
   137                 uint locatedVTable = locatedCell.PossibleVTableAddress;
       
   138 
       
   139                 // Compare length, type and vTable
       
   140                 if ( origType == locatedType )
       
   141                 {
       
   142                     // Type is the same...
       
   143                     if ( aCell.Length == locatedCell.Length )
       
   144                     {
       
   145                         CompareCellsWithSameLengths( aCell, locatedCell );
       
   146                     }
       
   147                     else
       
   148                     {
       
   149                         CompareCellsWithDifferentLengths( aCell, locatedCell );
       
   150                     }
       
   151                 }
       
   152                 else
       
   153                 {
       
   154                     // The cell is not of the same type, so they cannot have
       
   155                     // any commonality between them. Therefore they are unique in their
       
   156                     // respective heaps.
       
   157                     iUniqueInReconstructor1.Add( aCell );
       
   158                     iUniqueInReconstructor2.Add( locatedCell );
       
   159                 }
       
   160             }
       
   161             else
       
   162             {
       
   163                 // There wasn't any corresponding cell in the second list, so it's got to be
       
   164                 // unique to the first heap
       
   165                 iUniqueInReconstructor1.Add( aCell );
       
   166             }
       
   167         }
       
   168 
       
   169         protected override void HandleReadCompleted()
       
   170         {
       
   171             try
       
   172             {
       
   173                 base.HandleReadCompleted();
       
   174             }
       
   175             finally
       
   176             {
       
   177                 // Anything left behind in reconstructor 2 was unique to it.
       
   178                 int count = iReconstructor2.Data.Count;
       
   179                 int alreadyHave = iUniqueInReconstructor2.Count;
       
   180                 foreach ( HeapCell leftover in iReconstructor2.Data )
       
   181                 {
       
   182                     iUniqueInReconstructor2.Add( leftover );
       
   183                 }
       
   184                 System.Diagnostics.Debug.Assert( alreadyHave + count == iUniqueInReconstructor2.Count );
       
   185             }
       
   186 
       
   187             /*
       
   188             int unchanged = CountBySymbol( "CFsDisconnectRequest", iUnchanged );
       
   189             int diffContents = CountBySymbol( "CFsDisconnectRequest", iUnchangedLengthButDifferentContents );
       
   190             int changed = CountBySymbol( "CFsDisconnectRequest", iChanged );
       
   191             int unique1 = 0;// CountBySymbol( "CFsDisconnectRequest", iUniqueInReconstructor1 );
       
   192             int unique2 = CountBySymbol( "CFsDisconnectRequest", iUniqueInReconstructor2 );
       
   193 
       
   194             int total = unchanged + diffContents + changed + unique1 + unique2;
       
   195 
       
   196             int x = total;
       
   197             */
       
   198         }
       
   199         #endregion
       
   200 
       
   201         #region Internal methods
       
   202         private void CompareCellsWithSameLengths( HeapCell aFromRecon1, HeapCell aFromRecon2 )
       
   203         {
       
   204             System.Diagnostics.Debug.Assert( aFromRecon1.Tag == null );
       
   205             System.Diagnostics.Debug.Assert( aFromRecon1.Address == aFromRecon2.Address );
       
   206             System.Diagnostics.Debug.Assert( aFromRecon2.Type == aFromRecon2.Type );
       
   207             System.Diagnostics.Debug.Assert( aFromRecon1.Length == aFromRecon2.Length );
       
   208 
       
   209             // Cells are the same, at least at face value. We also compare
       
   210             // contents to spot those that are entirely [unchanged].
       
   211             bool equal = ( aFromRecon1.IsIdentical( aFromRecon2 ) );
       
   212             if ( equal )
       
   213             {
       
   214                 // Absolutely identical to one another
       
   215                 aFromRecon1.Tag = aFromRecon2;
       
   216                 iUnchanged.Add( aFromRecon1 );
       
   217             }
       
   218             else
       
   219             {
       
   220                 // Same length, same type, but otherwise the contents are different
       
   221                 //
       
   222                 // If it's an allocated cell and the vTables are different, then 
       
   223                 // the cell is treated as [unique].
       
   224                 //
       
   225                 // If it's a free cell, we don't care.
       
   226                 if ( aFromRecon2.Type == HeapCell.TType.EAllocated )
       
   227                 {
       
   228                     uint vt1 = aFromRecon1.IsUnknown ? 0 : aFromRecon1.PossibleVTableAddress;
       
   229                     uint vt2 = aFromRecon2.IsUnknown ? 0 : aFromRecon2.PossibleVTableAddress;
       
   230 
       
   231                     // If there was no associated symbol then the comparison will be zero vs
       
   232                     // zero, in which case we'll still treat it as the [same length, diff content],
       
   233                     // rather than unique. This might happen for blob cells, e.g. those that
       
   234                     // are the payload for RArray or CBufFlat etc.
       
   235                     if ( vt1 == vt2 )
       
   236                     {
       
   237                         // VTables are the same, but somehow the remaining content is different.
       
   238                         // Must also check whether one is a descriptor an the other isn't!
       
   239                         if ( aFromRecon1.IsDescriptor != aFromRecon2.IsDescriptor )
       
   240                         {
       
   241                             // One is a descriptor, the other isn't => [unique]
       
   242                             iUniqueInReconstructor1.Add( aFromRecon1 );
       
   243                             iUniqueInReconstructor2.Add( aFromRecon2 );
       
   244                         }
       
   245                         else
       
   246                         {
       
   247                             // [same length, diff content]
       
   248                             aFromRecon1.Tag = aFromRecon2;
       
   249                             iUnchangedLengthButDifferentContents.Add( aFromRecon1 );
       
   250                         }
       
   251                     }
       
   252                     else
       
   253                     {
       
   254                         // VTables are different, lengths and types are the same => [unique]
       
   255                         iUniqueInReconstructor1.Add( aFromRecon1 );
       
   256                         iUniqueInReconstructor2.Add( aFromRecon2 );
       
   257                     }
       
   258                 }
       
   259                 else
       
   260                 {
       
   261                     // Must be a free cell, and since the length is the same we
       
   262                     // really don't care => [same length, diff content]
       
   263                     aFromRecon1.Tag = aFromRecon2;
       
   264                     iUnchangedLengthButDifferentContents.Add( aFromRecon1 );
       
   265                 }
       
   266             }
       
   267         }
       
   268 
       
   269         private void CompareCellsWithDifferentLengths( HeapCell aFromRecon1, HeapCell aFromRecon2 )
       
   270         {
       
   271             System.Diagnostics.Debug.Assert( aFromRecon1.Tag == null );
       
   272             System.Diagnostics.Debug.Assert( aFromRecon1.Address == aFromRecon2.Address );
       
   273             System.Diagnostics.Debug.Assert( aFromRecon2.Type == aFromRecon2.Type );
       
   274             System.Diagnostics.Debug.Assert( aFromRecon1.Length != aFromRecon2.Length );
       
   275 
       
   276             if ( aFromRecon1.Type == HeapCell.TType.EFree )
       
   277             {
       
   278                 // Free cells, same address, different lengths => [changed]
       
   279                 aFromRecon1.Tag = aFromRecon2;
       
   280                 iChanged.Add( aFromRecon1 );
       
   281             }
       
   282             else if ( aFromRecon1.Type == HeapCell.TType.EAllocated )
       
   283             {
       
   284                 if ( aFromRecon1.IsUnknown && aFromRecon2.IsUnknown )
       
   285                 {
       
   286                     // Check if both are descriptors. If they are not, then
       
   287                     // assume unique.
       
   288                     if ( aFromRecon1.IsDescriptor != aFromRecon2.IsDescriptor )
       
   289                     {
       
   290                         // One is a descriptor, one isn't => [unique]
       
   291                         iUniqueInReconstructor1.Add( aFromRecon1 );
       
   292                         iUniqueInReconstructor2.Add( aFromRecon2 );
       
   293                     }
       
   294                     else
       
   295                     {
       
   296                         // Cells with unknown vTables, but at the same address are just assumed to be blobs that
       
   297                         // have grown or shrunk => [changed]
       
   298                         aFromRecon1.Tag = aFromRecon2;
       
   299                         iChanged.Add( aFromRecon1 );
       
   300                     }
       
   301                 }
       
   302                 else
       
   303                 {
       
   304                     uint vt1 = aFromRecon1.IsUnknown ? 0 : aFromRecon1.PossibleVTableAddress;
       
   305                     uint vt2 = aFromRecon2.IsUnknown ? 0 : aFromRecon2.PossibleVTableAddress;
       
   306 
       
   307                     // If either vTable is different, then they are [unique]. If the vTables
       
   308                     // are the same, then this is odd - classes with known vTables shouldn't change
       
   309                     // size dynamically?
       
   310                     if ( vt1 == vt2 )
       
   311                     {
       
   312                         // VTables are the same, but somehow the length has
       
   313                         // changed. I don't know what to do about this at the moment so
       
   314                         // am filing the cells in the unique bucket!
       
   315                         iUniqueInReconstructor1.Add( aFromRecon1 );
       
   316                         iUniqueInReconstructor2.Add( aFromRecon2 );
       
   317                     }
       
   318                     else
       
   319                     {
       
   320                         // VTables are different, lengths not the same, types is the same => [unique]
       
   321                         iUniqueInReconstructor1.Add( aFromRecon1 );
       
   322                         iUniqueInReconstructor2.Add( aFromRecon2 );
       
   323                     }
       
   324                 }
       
   325             }
       
   326         }
       
   327 
       
   328         private static bool CompareCommonContents( HeapCell aLeft, HeapCell aRight )
       
   329         {
       
   330             HeapCell smaller = aLeft;
       
   331             HeapCell larger = aRight;
       
   332             if ( aLeft.RawItems.Count > aRight.RawItems.Count )
       
   333             {
       
   334                 smaller = aRight;
       
   335                 larger = aLeft;
       
   336             }
       
   337 
       
   338             // The payload length is in bytes, the raw item count is in 32 bit words.
       
   339             // They should agree, once multipled by 4 - if not, something is badly borked.
       
   340             // We should probably throw an exception, but try to be tolerant for now...
       
   341             if ( smaller.RawItems.Count * 4 != smaller.PayloadLength )
       
   342             {
       
   343                 return false;
       
   344             }
       
   345             else if ( larger.RawItems.Count * 4 != larger.PayloadLength )
       
   346             {
       
   347                 return false;
       
   348             }
       
   349 
       
   350             int smallerSize = smaller.RawItems.Count;
       
   351             for ( int i = 0; i < smallerSize; i++ )
       
   352             {
       
   353                 RawItem itemS = smaller[ i ];
       
   354                 RawItem itemL = larger[ i ];
       
   355                 //
       
   356                 if ( itemS.Data != itemL.Data )
       
   357                 {
       
   358                     return false;
       
   359                 }
       
   360             }
       
   361 
       
   362             return true;
       
   363         }
       
   364 
       
   365         private static int CountBySymbol( string aText, HeapCellArray aArray )
       
   366         {
       
   367             int ret = 0;
       
   368             int count = aArray.Count;
       
   369             for ( int i = 0; i < count; i++ )
       
   370             {
       
   371                 HeapCell cell = aArray[ i ];
       
   372                 string sym = cell.SymbolStringWithoutDescriptorPrefix;
       
   373                 if ( sym.Contains( aText ) )
       
   374                 {
       
   375                     ++ret;
       
   376                 }
       
   377             }
       
   378             return ret;
       
   379         }
       
   380         #endregion
       
   381 
       
   382         #region Data members
       
   383         private readonly HeapReconstructor iReconstructor1;
       
   384         private readonly HeapReconstructor iReconstructor2;
       
   385         //
       
   386         private HeapCellArrayWithStatistics iUnchanged = new HeapCellArrayWithStatistics();
       
   387         private HeapCellArrayWithStatistics iUnchangedLengthButDifferentContents = new HeapCellArrayWithStatistics();
       
   388         private HeapCellArrayWithStatistics iChanged = new HeapCellArrayWithStatistics();
       
   389         private HeapCellArrayWithStatistics iUniqueInReconstructor1 = new HeapCellArrayWithStatistics();
       
   390         private HeapCellArrayWithStatistics iUniqueInReconstructor2 = new HeapCellArrayWithStatistics();
       
   391         #endregion
       
   392     }
       
   393 
       
   394     internal class ComparsionCellSupplierProxy : AsyncArrayObjectSupplier<HeapCell>
       
   395     {
       
   396         #region Constructors & destructor
       
   397         public ComparsionCellSupplierProxy( HeapReconstructor aReconstructor )
       
   398         {
       
   399             iReconstructor = aReconstructor;
       
   400         }
       
   401         #endregion
       
   402 
       
   403         #region AsyncArrayObjectSupplier<HeapCell> Members
       
   404         public int ObjectCount
       
   405         {
       
   406             get { return iReconstructor.Data.Count; }
       
   407         }
       
   408 
       
   409         public HeapCell this[ int aIndex ]
       
   410         {
       
   411             get { return iReconstructor.Data[ aIndex ]; }
       
   412         }
       
   413         #endregion
       
   414 
       
   415         #region Data members
       
   416         private readonly HeapReconstructor iReconstructor;
       
   417         #endregion
       
   418     }
       
   419 }