[mapguide-commits] r4386 - trunk/MgDev/Common/CoordinateSystem

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon Dec 7 19:27:39 EST 2009


Author: NormOlsen
Date: 2009-12-07 19:27:39 -0500 (Mon, 07 Dec 2009)
New Revision: 4386

Modified:
   trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp
   trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
   trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp
Log:
RFC 76 -- Testing has shown that some tuning on the memory use calculation was in order.  This submission deals with that issue.  Prior to submitting, it was verified using the help of _heapwalker that the calculated memory use is within 10% of reality.  Several obstacles to making a computation more accurate than this: 1> MgCoordinate objects with multiple references are counted multiple times, and 2> MgCollection often allocates a capacity for which a substantial portion is not used.  There are proably others that we have not discovered yet.

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp	2009-12-08 00:11:08 UTC (rev 4385)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysGrids.cpp	2009-12-08 00:27:39 UTC (rev 4386)
@@ -30,6 +30,16 @@
 
 using namespace CSLibrary;
 
+#if !defined (_DEBUG)
+    // Include heap overhead estinated at 12 bytes in release mode.
+    static const INT32 kMgHeapOverhead = 12;
+    static const INT32 kMgSizeOfCoordinateXY = sizeof (MgCoordinateXY) + kMgHeapOverhead;
+#else
+    // Include heap overhead estinated at 48 bytes in release mode.
+    static const INT32 kMgHeapOverhead = 36;
+    static const INT32 kMgSizeOfCoordinateXY = sizeof (MgCoordinateXY) + kMgHeapOverhead;
+#endif
+
 //=============================================================================
 // CCoordinateSystemGridSpecification -- Assembly which contains all grid
 //                                       parameter values.
@@ -662,10 +672,9 @@
 }
 INT32 CCoordinateSystemGridLine::GetMemoryUsage ()
 {
-    static const INT32 sizeOfMgCoordinateXY = 24;
     INT32 lineIndex;
     INT32 lineCount;
-    INT32 memoryUse = sizeof (CCoordinateSystemGridLine);
+    INT32 memoryUse = sizeof (CCoordinateSystemGridLine) + kMgHeapOverhead;
 
     lineCount = m_LineSegments->GetCount ();
     for (lineIndex = 0;lineIndex < lineCount;lineIndex += 1)
@@ -673,10 +682,11 @@
         Ptr<MgLineString> lineStringPtr = m_LineSegments->GetItem (lineIndex);
         if (lineStringPtr != 0)
         {
+            memoryUse += sizeof (MgLineString) + kMgHeapOverhead;
             Ptr<MgCoordinateIterator> pointItr = lineStringPtr->GetCoordinates ();
             while (pointItr->MoveNext ())
             {
-                memoryUse += sizeOfMgCoordinateXY;
+                memoryUse += kMgSizeOfCoordinateXY;
             }
         }
     }
@@ -807,17 +817,21 @@
 INT32 CCoordinateSystemGridRegion::GetMemoryUsage ()
 {
     INT32 memoryUse;
-    static const INT32 sizeOfMgCoordinateXY = 24;
 
-    memoryUse  = sizeof (CCoordinateSystemGridRegion);
+    memoryUse  = sizeof (CCoordinateSystemGridRegion) + kMgHeapOverhead;
     memoryUse += sizeof (STRING);
     memoryUse += m_RegionLabel.capacity () * sizeof (wchar_t);
-    memoryUse += sizeOfMgCoordinateXY;
+    memoryUse += kMgSizeOfCoordinateXY;
     memoryUse += PolygonMemoryUse (m_RegionBoundary.p);
     memoryUse += LineStringCollectionMemoryUse (m_SouthLine.p);
     memoryUse += LineStringCollectionMemoryUse (m_EastLine.p);
     memoryUse += LineStringCollectionMemoryUse (m_NorthLine.p);
     memoryUse += LineStringCollectionMemoryUse (m_WestLine.p);
+
+    // Testing has shown the above calculation to be about 20% low.
+    // This is assumed to be because collections have a capacity and a useage,
+    // and while we measure usage above, we can't measure capacity.
+    memoryUse += memoryUse / 5;
     return memoryUse;
 }
 void CCoordinateSystemGridRegion::SetRegionBoundary (MgPolygon* boundary)
@@ -846,43 +860,42 @@
 }
 INT32 CCoordinateSystemGridRegion::PolygonMemoryUse (MgPolygon* polygon)
 {
-    // WHile MgPolygon objects support holes, there are no holes in a Region
+    // While MgPolygon objects support holes, there are no holes in a Region
     // (so far anyway); so we only evaluate the exterior ring.
 
-    static const INT32 sizeOfMgCoordinateXY = 24;
-    INT32 memoryUse (0);
+    INT32 memoryUse;
 
+    memoryUse = sizeof (MgPolygon) + kMgHeapOverhead;
     if (polygon != 0)
     {
         Ptr<MgCoordinateIterator> pointItr = polygon->GetCoordinates ();
         while (pointItr->MoveNext ())
         {
-            memoryUse += sizeOfMgCoordinateXY;
+            memoryUse += kMgSizeOfCoordinateXY;
         }
     }
     return memoryUse;
 }
 INT32 CCoordinateSystemGridRegion::LineStringCollectionMemoryUse (MgLineStringCollection* lineCollection)
 {
-    static const INT32 sizeOfMgCoordinateXY = 24;
     INT32 memoryUse (0);
     INT32 lineCount;
     INT32 lineIndex;
 
     if (lineCollection != 0)
     {
-        memoryUse += sizeof (MgLineStringCollection);
+        memoryUse += sizeof (MgLineStringCollection) + kMgHeapOverhead;
         lineCount = lineCollection->GetCount ();
         for (lineIndex = 0;lineIndex < lineCount;lineIndex += 1)
         {
             Ptr<MgLineString> lineStringPtr = lineCollection->GetItem (lineIndex);
             if (lineStringPtr != 0)
             {
-                memoryUse += sizeof (MgLineString);
+                memoryUse += sizeof (MgLineString) + kMgHeapOverhead;
                 Ptr<MgCoordinateIterator> pointItr = lineStringPtr->GetCoordinates ();
                 while (pointItr->MoveNext ())
                 {
-                    memoryUse += sizeOfMgCoordinateXY;
+                    memoryUse += kMgSizeOfCoordinateXY;
                 }
             }
         }
@@ -954,9 +967,8 @@
 }
 INT32 CCoordinateSystemGridTick::GetMemoryUsage ()
 {
-    static const INT32 MgSizeOfCoordinateXY = 24;
-    INT32 memoryUse = sizeof (CCoordinateSystemGridTick);
-    memoryUse += 2 * MgSizeOfCoordinateXY;
+    INT32 memoryUse = sizeof (CCoordinateSystemGridTick) + kMgHeapOverhead;
+    memoryUse += (kMgSizeOfCoordinateXY + kMgSizeOfCoordinateXY);
     return memoryUse;
 }
 void CCoordinateSystemGridTick::Dispose ()
@@ -972,10 +984,11 @@
 CCoordinateSystemGridLineCollection::CCoordinateSystemGridLineCollection (INT32 gridLineExceptionLevel)
                                         :
                                      MgCoordinateSystemGridLineCollection (),
-                                     m_MemoryUse                          (0),
+                                     m_MemoryUse                          (),
                                      m_GridLineExceptionLevel             (gridLineExceptionLevel),
                                      m_GridLineCollection                 ()
 {
+    m_MemoryUse = sizeof (MgCoordinateSystemGridLineCollection) + sizeof (MgDisposableCollection);
     m_GridLineCollection = new MgDisposableCollection();
 }
 CCoordinateSystemGridLineCollection::~CCoordinateSystemGridLineCollection(void)
@@ -1030,10 +1043,16 @@
     // The MgDisposableCollection object checks the index argument, and throws if appropriate.
     // The MgDisposableCollection object performs the "SAFE_RELEASE" operation.
 
-    Ptr<MgCoordinateSystemGridLine> gridLinePtr = this->GetItem (index);
-    if (gridLinePtr != 0)
+    if (index >= 0 && index < GetCount ())
     {
-        memoryUse = gridLinePtr->GetMemoryUsage ();
+        // We don't want an invalid index exception thrown from this GetItem,
+        // we leave that to the RemoveAt function.  Also, this releases the
+        // pointer we get before the exception is thrown.
+        Ptr<MgCoordinateSystemGridLine> gridLinePtr = GetItem (index);
+        if (gridLinePtr != 0)
+        {
+            memoryUse = gridLinePtr->GetMemoryUsage ();
+        }
     }
     m_GridLineCollection->RemoveAt (index);
     m_MemoryUse -= memoryUse;
@@ -1042,13 +1061,29 @@
 {
     // The MgDisposableCollection object performs the "SAFE_RELEASE" operation.
     m_GridLineCollection->Clear ();
-    m_MemoryUse = 0;
+    m_MemoryUse = sizeof (MgCoordinateSystemGridLineCollection) + sizeof (MgDisposableCollection);
 }
 void CCoordinateSystemGridLineCollection::SetItem (INT32 index,MgCoordinateSystemGridLine* value)
 {
-    // The MgDisposableCollection object checks the index argument, and throws if appropriate.
-    // The MgDisposableCollection object performs the "SAFE_RELEASE" & "SAFE_ADDREF" operations.
-    m_GridLineCollection->SetItem (index,value);
+    INT32 memoryUse (0);
+
+    memoryUse = value->GetMemoryUsage ();
+    if (index >= 0 && index < GetCount ())
+    {
+        Ptr<MgCoordinateSystemGridLine> oldGridLine = GetItem (index);
+        if (oldGridLine != 0)
+        {
+            memoryUse -= oldGridLine->GetMemoryUsage ();
+        }
+    }
+    if ((m_MemoryUse + memoryUse) < m_GridLineExceptionLevel)
+    {
+        m_GridLineCollection->SetItem (index,value);
+    }
+    else
+    {
+        throw new MgGridDensityException(L"CCoordinateSystemGridLineCollection.SetItem", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
 }
 void CCoordinateSystemGridLineCollection::Add (MgCoordinateSystemGridLine* value)
 {
@@ -1108,10 +1143,11 @@
 CCoordinateSystemGridRegionCollection::CCoordinateSystemGridRegionCollection (INT32 gridRegionExceptionLevel)
                                          :
                                        MgCoordinateSystemGridRegionCollection (),
-                                       m_MemoryUse                            (0),
+                                       m_MemoryUse                            (),
                                        m_GridRegionExceptionLevel             (gridRegionExceptionLevel),
                                        m_GridRegionCollection                 ()
 {
+    m_MemoryUse = sizeof (CCoordinateSystemGridRegionCollection) + sizeof (MgDisposableCollection);
     m_GridRegionCollection = new MgDisposableCollection();
 }
 CCoordinateSystemGridRegionCollection::~CCoordinateSystemGridRegionCollection (void)
@@ -1132,26 +1168,44 @@
 }
 void CCoordinateSystemGridRegionCollection::RemoveAt (INT32 index)
 {
+    INT32 memoryUse (0);
+
     // The MgDisposableCollection object checks the index argument, and throws if appropriate.
     // The MgDisposableCollection object performs the "SAFE_RELEASE" operation.
+
+    if (index >= 0 && index < GetCount ())
+    {
+        // We don't want an invalid index exception thrown from this GetItem,
+        // we leave that to the RemoveAt function.  Also, this releases the
+        // pointer we get before the exception is thrown.
+        Ptr<MgCoordinateSystemGridRegion> gridRegionPtr = GetItem (index);
+        if (gridRegionPtr != 0)
+        {
+            memoryUse = gridRegionPtr->GetMemoryUsage ();
+        }
+    }
     m_GridRegionCollection->RemoveAt (index);
+    m_MemoryUse -= memoryUse;
 }
 void CCoordinateSystemGridRegionCollection::Clear()
 {
     m_GridRegionCollection->Clear ();
-    m_MemoryUse = 0;
+    m_MemoryUse = sizeof (CCoordinateSystemGridRegionCollection) + sizeof (MgDisposableCollection);
 }
 void CCoordinateSystemGridRegionCollection::SetItem (INT32 index, MgCoordinateSystemGridRegion* value)
 {
     INT32 memoryUse;
 
-    Ptr<MgCoordinateSystemGridRegion> currentPtr = static_cast<MgCoordinateSystemGridRegion*>(m_GridRegionCollection->GetItem (index));
-    if (currentPtr != 0)
+    memoryUse = value->GetMemoryUsage ();
+    if (index >= 0 && index < GetCount ())
     {
-        m_MemoryUse -= currentPtr->GetMemoryUsage ();
+        Ptr<MgCoordinateSystemGridRegion> currentPtr = GetItem (index);
+        if (currentPtr != 0)
+        {
+            memoryUse -= currentPtr->GetMemoryUsage ();
+        }
     }
-    memoryUse = value->GetMemoryUsage ();
-    if ((memoryUse + m_MemoryUse) < m_GridRegionExceptionLevel)
+    if ((m_MemoryUse + memoryUse) < m_GridRegionExceptionLevel)
     {
         m_GridRegionCollection->SetItem (index,value);
         m_MemoryUse += memoryUse;
@@ -1220,10 +1274,11 @@
 CCoordinateSystemGridTickCollection::CCoordinateSystemGridTickCollection (INT32 gridTickExceptionLevel)
                                         :
                                      MgCoordinateSystemGridTickCollection (),
-                                     m_MemoryUse                          (0),
+                                     m_MemoryUse                          (),
                                      m_GridTickExceptionLevel             (gridTickExceptionLevel),
                                      m_GridTickCollection                 ()
 {
+    m_MemoryUse = sizeof (CCoordinateSystemGridTickCollection) + sizeof (MgDisposableCollection);
     m_GridTickCollection = new MgDisposableCollection();
 }
 CCoordinateSystemGridTickCollection::~CCoordinateSystemGridTickCollection (void)
@@ -1242,16 +1297,53 @@
 }
 void CCoordinateSystemGridTickCollection::RemoveAt (INT32 index)
 {
+    INT32 memoryUse (0);
+
+    // The MgDisposableCollection object checks the index argument, and throws if appropriate.
+    // The MgDisposableCollection object performs the "SAFE_RELEASE" operation.
+
+    if (index >= 0 && index < GetCount ())
+    {
+        // We don't want an invalid index exception thrown from this GetItem,
+        // we leave that to the RemoveAt function.  Also, this releases the
+        // pointer we get before the exception is thrown.
+        Ptr<MgCoordinateSystemGridTick> gridTickPtr = GetItem (index);
+        if (gridTickPtr != 0)
+        {
+            memoryUse = gridTickPtr->GetMemoryUsage ();
+        }
+    }
     m_GridTickCollection->RemoveAt (index);
+    m_MemoryUse -= memoryUse;
 }
 void CCoordinateSystemGridTickCollection::Clear()
 {
     m_GridTickCollection->Clear ();
-    m_MemoryUse = 0;
+    m_MemoryUse = sizeof (CCoordinateSystemGridTickCollection) + sizeof (MgDisposableCollection);
 }
 void CCoordinateSystemGridTickCollection::SetItem (INT32 index, MgCoordinateSystemGridTick* value)
 {
-    m_GridTickCollection->SetItem (index,value);
+    INT32 memoryUse;
+
+    memoryUse = value->GetMemoryUsage ();
+    if (index >= 0 && index < GetCount ())
+    {
+        Ptr<MgCoordinateSystemGridTick> currentPtr = GetItem (index);
+        if (currentPtr != 0)
+        {
+            memoryUse -= currentPtr->GetMemoryUsage ();
+        }
+    }
+    if ((m_MemoryUse + memoryUse) < m_GridTickExceptionLevel)
+    {
+        m_GridTickCollection->SetItem (index,value);
+        m_MemoryUse += memoryUse;
+    }
+    else
+    {
+        throw new MgGridDensityException(L"CCoordinateSystemGridTickCollection.SetItem", __LINE__, __WFILE__, NULL, L"", NULL);
+    }
+
 }
 void CCoordinateSystemGridTickCollection::Add (MgCoordinateSystemGridTick* value)
 {

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp	2009-12-08 00:11:08 UTC (rev 4385)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysMgrsZone.cpp	2009-12-08 00:27:39 UTC (rev 4386)
@@ -29,6 +29,16 @@
 
 using namespace CSLibrary;
 
+#if !defined (_DEBUG)
+    // Include heap overhead estinated at 12 bytes in release mode.
+    static const INT32 kMgHeapOverhead = 12;
+    static const INT32 kMgSizeOfCoordinateXY = sizeof (MgCoordinateXY) + kMgHeapOverhead;
+#else
+    // Include heap overhead estinated at 48 bytes in release mode.
+    static const INT32 kMgHeapOverhead = 36;
+    static const INT32 kMgSizeOfCoordinateXY = sizeof (MgCoordinateXY) + kMgHeapOverhead;
+#endif
+
 CCoordinateSystemMgrsZone::CCoordinateSystemMgrsZone (MgCoordinateSystemGridBoundary* frameBoundary,
                                                       INT32 utmZoneNbr,
                                                       bool useFrameDatum,
@@ -232,11 +242,27 @@
     INT32 regionCount;
     INT32 memoryGuess (0);
 
-    
-
     // Estimate the size of a major region object.  Eventually, should include
-    // MaxPoints and curve precision from the specification object.
-    regionSize = (GridFrameCrsAreTheSame ()) ? 512 : 50000;
+    // MaxPoints and CurvePrecision from the specification object.  For now, we
+    // make some guesses based on the coordinate systems involved.
+    if (GridFrameCrsAreTheSame ())
+    {
+        // Here, for now, we assume that there are 4 lines at two points a piece, plus
+        // a polygon with 5 points.  In this case, several of these points are the
+        // same actual object in memory; so we reduce the point count by (an arbirtrary
+        // value) 3.
+        regionSize = sizeof (CCoordinateSystemGridRegion) + sizeof (MgPolygon) +
+                                                            sizeof (MgLineString) * 4 +
+                                                            kMgSizeOfCoordinateXY * 10;
+    }
+    else
+    {
+        // Here, for now, we assume that there are 4 lines at 511 points a piece, plus
+        // a polygon with (4 * 511) points; 4088 points altogether.
+        regionSize = sizeof (CCoordinateSystemGridRegion) + sizeof (MgPolygon) +
+                                                            sizeof (MgLineString) * 4 +
+                                                            kMgSizeOfCoordinateXY * 4088;
+    }
 
     MG_TRY ()
         if (specification->GetUnitType () == MgCoordinateSystemUnitType::Angular)

Modified: trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp
===================================================================
--- trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp	2009-12-08 00:11:08 UTC (rev 4385)
+++ trunk/MgDev/Common/CoordinateSystem/CoordSysOneGrid.cpp	2009-12-08 00:27:39 UTC (rev 4386)
@@ -28,6 +28,14 @@
 
 using namespace CSLibrary;
 
+#if !defined (_DEBUG)
+    // Include heap overhead estinated at 12 bytes in release mode.
+    static const INT32 kMgSizeOfCoordinateXY = sizeof (MgCoordinateXY) + 12;
+#else
+    // Include heap overhead estinated at 48 bytes in release mode.
+    static const INT32 kMgSizeOfCoordinateXY = sizeof (MgCoordinateXY) + 48;
+#endif
+
 //=============================================================================
 // CCoordinateSystemOneGrid
 const INT32 CCoordinateSystemOneGrid::MaxCurvePoints = 511;
@@ -418,7 +426,85 @@
 
 INT32 CCoordinateSystemOneGrid::ApproxGridLineMemoryUsage (MgCoordinateSystemGridSpecification* specification)
 {
-    return 50000;
+    INT32 memoryUse (5000000);
+    INT32 lineSize;
+    INT32 lineCount;
+    INT32 gridCrsUnitCode;
+
+    double delta;
+    double increment;
+    double precision;
+    double eastMin, eastMax;
+    double northMin, northMax;
+
+    // We'll compute the number of grid lines which can be expected given the
+    // provided specification.  For now, we just make a guess at the size of
+    // each line based on the coordinate systems involved.
+    if (m_GridFrameCrsSame)
+    {
+        lineSize = sizeof (CCoordinateSystemGridLine) + sizeof (MgLineStringCollection) + 
+                                                        sizeof (MgLineString) +
+                                                        kMgSizeOfCoordinateXY * 2;
+    }
+    else
+    {
+        lineSize = sizeof (CCoordinateSystemGridLine) + sizeof (MgLineStringCollection) + 
+                                                        sizeof (MgLineString) * 2 +
+                                                        kMgSizeOfCoordinateXY * 511;
+    }
+
+    // TODO --> The folowing 40 or so lines of code are a cut and paste from
+    // the line generator code above.  This should be placed in a separate function
+    // to eliminate duplicate code.  For now, we jkust want to see how well all
+    // of this memory management stuff works.
+    MG_TRY ()
+        gridCrsUnitCode = m_GridCRS->GetUnitCode ();
+        CCoordinateSystemGridSpecification* mySpecPtr = dynamic_cast<CCoordinateSystemGridSpecification*>(specification);
+        precision = mySpecPtr->GetCurvePrecision (m_GridCRS);
+        // The following does not generate a boundary if it has already been
+        // generated.
+        GenerateGridBoundary (precision);
+
+        // Compute the range of the grid line generation.
+        m_GridBoundary->GetBoundaryExtents (eastMin,eastMax,northMin,northMax);
+        
+        // Expand the range to include all grid values at the extents.
+        increment = mySpecPtr->GetEastingIncrement(gridCrsUnitCode);
+        delta = fabs(fmod (eastMin,increment));
+        eastMin -= (eastMin >= 0.0) ? delta : (increment - delta);
+        delta = fabs(fmod (eastMax,increment));
+        eastMax += (eastMax >= 0.0) ? (increment - delta) : delta;
+ 
+        increment = mySpecPtr->GetNorthingIncrement(gridCrsUnitCode);
+        delta = fabs(fmod (northMin,increment));
+        northMin -= (northMin >= 0.0) ? delta : (increment - delta);
+        delta = fabs(fmod (northMax,increment));
+        northMax += (northMax >= 0.0) ? (increment - delta) : delta;
+
+        // Adjust for the base.  Again, we always enlarge, never shrink.
+        if (mySpecPtr->GetEastingBase () > 0.0)
+        {
+            increment = mySpecPtr->GetEastingIncrement (gridCrsUnitCode);
+            delta = fmod (mySpecPtr->GetEastingBase(gridCrsUnitCode),increment);
+            eastMin  += delta - increment;
+            eastMax  += delta + increment;
+        }
+        if (mySpecPtr->GetNorthingBase () > 0.0)
+        {
+            increment = mySpecPtr->GetNorthingIncrement (gridCrsUnitCode);
+            delta = fmod (mySpecPtr->GetNorthingBase(gridCrsUnitCode),increment);
+            northMin  += delta - increment;
+            northMax  += delta + increment;
+        }
+
+        // Compute the number of grid line objects we will need to create.
+        increment = mySpecPtr->GetEastingIncrement(gridCrsUnitCode);
+        lineCount = static_cast<INT32>(fabs (eastMax - eastMin) / increment);
+        increment = mySpecPtr->GetNorthingIncrement(gridCrsUnitCode);
+        lineCount += static_cast<INT32>(fabs (northMax - northMin) / increment);
+        memoryUse = lineCount * lineSize;
+    MG_CATCH_AND_RELEASE()
+    return memoryUse;
 }
 INT32 CCoordinateSystemOneGrid::ApproxGridTickMemoryUsage (MgCoordinateSystemGridSpecification* specification)
 {



More information about the mapguide-commits mailing list