# Too big memory footprint

**URL:** <https://community.thinkgeo.com/t/too-big-memory-footprint/1999>\
**Category:** WinForms\
**Created:** [June 14, 2012, 3:22am UTC](https://community.thinkgeo.com/t/too-big-memory-footprint/1999 "2012-06-14T03:22:46Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ioannis](https://community.thinkgeo.com/letter_avatar_proxy/v4/letter/i/ad7895/32.png) [@Ioannis](https://community.thinkgeo.com/u/Ioannis)\
**Post date:** [June 14, 2012, 3:22am UTC](https://community.thinkgeo.com/t/too-big-memory-footprint/1999/1 "2012-06-14T03:22:46Z")

</div>

Hello&nbsp;all,

I&nbsp;have&nbsp;been&nbsp;fighting&nbsp;with&nbsp;realy&nbsp;large&nbsp;datasets&nbsp;from&nbsp;databases&nbsp;for&nbsp;quite&nbsp;long&nbsp;time.&nbsp;I&nbsp;have&nbsp;also&nbsp;tried&nbsp;to&nbsp;produce&nbsp;my&nbsp;own&nbsp;MapSuite&nbsp;database&nbsp;implementation&nbsp;in&nbsp;order&nbsp;to&nbsp;find&nbsp;out&nbsp;why&nbsp;my&nbsp;pc&nbsp;memory&nbsp;usage&nbsp;by&nbsp;the&nbsp;MapSuite&nbsp;application&nbsp;is&nbsp;so&nbsp;huge.&nbsp;So&nbsp;long&nbsp;I&nbsp;have&nbsp;find&nbsp;out&nbsp;that&nbsp;the&nbsp;API&nbsp;requires&nbsp;that&nbsp;the&nbsp;GetFeaturesInsideBoundingBoxCore&nbsp;returns&nbsp;a&nbsp;Collection&nbsp;of&nbsp;Features.&nbsp;It&nbsp;is&nbsp;these&nbsp;features&nbsp;that&nbsp;are&nbsp;stored&nbsp;in&nbsp;memory&nbsp;before&nbsp;returned&nbsp;to&nbsp;the&nbsp;core&nbsp;implementation&nbsp;for&nbsp;presentation&nbsp;that&nbsp;are&nbsp;filling&nbsp;up&nbsp;the&nbsp;RAM.&nbsp;Not&nbsp;sure&nbsp;if&nbsp;there&nbsp;are&nbsp;any&nbsp;other&nbsp;solution&nbsp;&nbsp;to&nbsp;this&nbsp;problem,&nbsp;like&nbsp;for&nbsp;example&nbsp;drawing&nbsp;the&nbsp;points&nbsp;as&nbsp;they&nbsp;come&nbsp;thus&nbsp;reducing&nbsp;the&nbsp;need&nbsp;to&nbsp;store&nbsp;the&nbsp;Features&nbsp;in&nbsp;memory&nbsp;and&nbsp;then&nbsp;taking&nbsp;advantage&nbsp;of&nbsp;the&nbsp;screen&nbsp;coords&nbsp;to&nbsp;retrieve&nbsp;more&nbsp;information.&nbsp;The&nbsp;basic&nbsp;implementation&nbsp;I&nbsp;use&nbsp;is&nbsp;as&nbsp;follows:

`Protected Overrides Function GetFeaturesInsideBoundingBoxCore(boundingBox As ThinkGeo.MapSuite.Core.RectangleShape, returningColumnNames As System.Collections.Generic.IEnumerable(Of String)) As System.Collections.ObjectModel.Collection(Of ThinkGeo.MapSuite.Core.Feature)  Dim retFeatures As New System.Collections.ObjectModel.Collection(Of ThinkGeo.MapSuite.Core.Feature)  Dim buildMBR As String = "BuildMBR(" & boundingBox.UpperLeftPoint.X & "," & boundingBox.UpperLeftPoint.Y & "," & boundingBox.LowerRightPoint.X & "," & boundingBox.LowerRightPoint.Y & ")"  Dim selectAllFeaturesCommand As New SQLiteCommand("select *, AsText(" & mTableInfo.GeometryColumnName & ") as geom from " & mTableInfo.TableName & " Where MBRContains(" & buildMBR & "," & mTableInfo.GeometryColumnName & ")", mSqLiteConn)  Dim allFeaturesReader = selectAllFeaturesCommand.ExecuteReader()  If allFeaturesReader.HasRows Then  While allFeaturesReader.Read  Dim wkt = DirectCast(allFeaturesReader("geom"), String)  Dim aFeature = New Feature(wkt)  retFeatures.Add(aFeature)  End While  End If  allFeaturesReader.Close()  Return retFeatures  End Function`

Any&nbsp;advice&nbsp;will&nbsp;be&nbsp;much&nbsp;appreciated.

Kind&nbsp;Regards

Yiannis

---

<div class="post-metadata">

**Author:** ![David](https://community.thinkgeo.com/letter_avatar_proxy/v4/letter/d/aeb1de/32.png) [@David](https://community.thinkgeo.com/u/David)\
**Post date:** [June 14, 2012, 6:46am UTC](https://community.thinkgeo.com/t/too-big-memory-footprint/1999/2 "2012-06-14T06:46:45Z")

</div>

Yiannis,

&nbsp;&nbsp;I&nbsp;understand&nbsp;your&nbsp;issue&nbsp;and&nbsp;I&nbsp;think&nbsp;I&nbsp;can&nbsp;help&nbsp;you&nbsp;with&nbsp;this.&nbsp;&nbsp;First&nbsp;let&nbsp;me&nbsp;start&nbsp;with&nbsp;a&nbsp;little&nbsp;background&nbsp;on&nbsp;why&nbsp;we&nbsp;created&nbsp;the&nbsp;API&nbsp;this&nbsp;way&nbsp;and&nbsp;proceed&nbsp;to&nbsp;a&nbsp;solution.&nbsp;&nbsp;The&nbsp;reason&nbsp;we&nbsp;wanted&nbsp;to&nbsp;get&nbsp;all&nbsp;of&nbsp;the&nbsp;features&nbsp;was&nbsp;that&nbsp;there&nbsp;are&nbsp;a&nbsp;number&nbsp;of&nbsp;styles,&nbsp;or&nbsp;ways&nbsp;of&nbsp;rendering,&nbsp;which&nbsp;need&nbsp;all&nbsp;of&nbsp;the&nbsp;data&nbsp;to&nbsp;render&nbsp;properly.&nbsp;&nbsp;An&nbsp;example&nbsp;would&nbsp;be&nbsp;the&nbsp;heat&nbsp;style,&nbsp;cluster&nbsp;style,&nbsp;labeling&nbsp;etc.&nbsp;&nbsp;Since&nbsp;we&nbsp;knew&nbsp;we&nbsp;had&nbsp;to&nbsp;support&nbsp;this&nbsp;it&nbsp;influenced&nbsp;our&nbsp;architecture.&nbsp;&nbsp;Looking&nbsp;back&nbsp;it&nbsp;might&nbsp;not&nbsp;have&nbsp;been&nbsp;the&nbsp;best&nbsp;choice.&nbsp;&nbsp;We&nbsp;were&nbsp;fortunate&nbsp;because&nbsp;in&nbsp;most&nbsp;of&nbsp;our&nbsp;products&nbsp;the&nbsp;drawing&nbsp;is&nbsp;done&nbsp;on&nbsp;a&nbsp;per&nbsp;tile&nbsp;basis&nbsp;and&nbsp;tiles&nbsp;are&nbsp;relatively&nbsp;small&nbsp;so&nbsp;it&nbsp;helped&nbsp;by&nbsp;not&nbsp;processing&nbsp;too&nbsp;much&nbsp;data&nbsp;at&nbsp;once.

&nbsp;&nbsp;As&nbsp;our&nbsp;products&nbsp;progressed&nbsp;we&nbsp;started&nbsp;to&nbsp;notice&nbsp;the&nbsp;memory&nbsp;pressure&nbsp;that&nbsp;you&nbsp;mentioned&nbsp;and&nbsp;we&nbsp;made&nbsp;some&nbsp;changes&nbsp;to&nbsp;our&nbsp;most&nbsp;popular&nbsp;FeatureLayer,&nbsp;the&nbsp;ShapeFileFeatureLayer,&nbsp;to&nbsp;address&nbsp;this.&nbsp;&nbsp;What&nbsp;we&nbsp;did&nbsp;was&nbsp;to&nbsp;override&nbsp;the&nbsp;DrawCore&nbsp;method&nbsp;on&nbsp;the&nbsp;ShapeFileFeatureLayer&nbsp;and&nbsp;where&nbsp;we&nbsp;would&nbsp;normally&nbsp;call&nbsp;the&nbsp;GetFeaturesForDrawing&nbsp;on&nbsp;the&nbsp;FeatureSource&nbsp;we&nbsp;instead&nbsp;called&nbsp;a&nbsp;new&nbsp;method&nbsp;to&nbsp;get&nbsp;the&nbsp;FeatureIds&nbsp;for&nbsp;drawing&nbsp;in&nbsp;the&nbsp;bounding&nbsp;box.&nbsp;&nbsp;We&nbsp;then&nbsp;loaded&nbsp;the&nbsp;real&nbsp;shapes&nbsp;from&nbsp;the&nbsp;Ids&nbsp;in&nbsp;chunks&nbsp;and&nbsp;when&nbsp;we&nbsp;had&nbsp;a&nbsp;chunk&nbsp;ready&nbsp;we&nbsp;called&nbsp;the&nbsp;rest&nbsp;of&nbsp;the&nbsp;drawing&nbsp;pipeline&nbsp;with&nbsp;just&nbsp;those&nbsp;features.&nbsp;&nbsp;When&nbsp;the&nbsp;next&nbsp;chunk&nbsp;was&nbsp;ready&nbsp;we&nbsp;sent&nbsp;that&nbsp;through.&nbsp;&nbsp;In&nbsp;this&nbsp;way&nbsp;we&nbsp;cut&nbsp;the&nbsp;memory&nbsp;pressure&nbsp;and&nbsp;increased&nbsp;performance.&nbsp;&nbsp;The&nbsp;price&nbsp;was&nbsp;that&nbsp;some&nbsp;of&nbsp;the&nbsp;styles&nbsp;I&nbsp;mentioned&nbsp;do&nbsp;not&nbsp;work&nbsp;well&nbsp;with&nbsp;the&nbsp;default&nbsp;ShapeFileFeatureLayer.&nbsp;&nbsp;To&nbsp;address&nbsp;that&nbsp;we&nbsp;made&nbsp;the&nbsp;'chunk'&nbsp;size&nbsp;configurable&nbsp;so&nbsp;that&nbsp;you&nbsp;can&nbsp;set&nbsp;it&nbsp;to&nbsp;int.max&nbsp;if&nbsp;you&nbsp;wanted&nbsp;to&nbsp;force&nbsp;it&nbsp;to&nbsp;draw&nbsp;the&nbsp;way&nbsp;it&nbsp;did&nbsp;before&nbsp;in&nbsp;one&nbsp;big&nbsp;chunk.

&nbsp;&nbsp;The&nbsp;plans&nbsp;for&nbsp;the&nbsp;future&nbsp;is&nbsp;to&nbsp;adapt&nbsp;our&nbsp;API&nbsp;in&nbsp;such&nbsp;a&nbsp;way&nbsp;that&nbsp;we&nbsp;can&nbsp;support&nbsp;this&nbsp;by&nbsp;default.&nbsp;&nbsp;At&nbsp;this&nbsp;moment&nbsp;it&nbsp;is&nbsp;behind&nbsp;some&nbsp;other&nbsp;large&nbsp;API&nbsp;changes&nbsp;such&nbsp;as&nbsp;the&nbsp;elimination&nbsp;of&nbsp;Shapes&nbsp;going&nbsp;with&nbsp;a&nbsp;new&nbsp;version&nbsp;of&nbsp;Features.&nbsp;&nbsp;This&nbsp;will&nbsp;all&nbsp;be&nbsp;announced&nbsp;pretty&nbsp;soon.&nbsp;&nbsp;After&nbsp;this&nbsp;is&nbsp;complete&nbsp;I&nbsp;believe&nbsp;this&nbsp;is&nbsp;the&nbsp;next&nbsp;major&nbsp;thing&nbsp;on&nbsp;the&nbsp;list&nbsp;related&nbsp;to&nbsp;the&nbsp;long&nbsp;term&nbsp;API&nbsp;trajectory.

&nbsp;&nbsp;Back&nbsp;to&nbsp;your&nbsp;situation.&nbsp;&nbsp;I&nbsp;think&nbsp;you&nbsp;can&nbsp;keep&nbsp;your&nbsp;GetFeatureInBoundingBoxCore&nbsp;intact&nbsp;as&nbsp;we&nbsp;will&nbsp;still&nbsp;need&nbsp;this.&nbsp;&nbsp;Instead&nbsp;we&nbsp;are&nbsp;going&nbsp;to&nbsp;override&nbsp;the&nbsp;DrawCore&nbsp;and&nbsp;put&nbsp;in&nbsp;some&nbsp;logic&nbsp;to&nbsp;call&nbsp;a&nbsp;new&nbsp;API&nbsp;you&nbsp;are&nbsp;going&nbsp;to&nbsp;add&nbsp;on&nbsp;your&nbsp;FeatureSource.&nbsp;&nbsp;&nbsp;Here&nbsp;is&nbsp;what&nbsp;you&nbsp;need&nbsp;to&nbsp;do..

1. Create&nbsp;a&nbsp;new&nbsp;method&nbsp;on&nbsp;your&nbsp;FeaureSource&nbsp;that&nbsp;allows&nbsp;you&nbsp;get&nbsp;a&nbsp;check&nbsp;of&nbsp;your&nbsp;data.&nbsp;&nbsp;Something&nbsp;like&nbsp;GetRecordsForDrawing&nbsp;but&nbsp;instead&nbsp;you&nbsp;pass&nbsp;it&nbsp;how&nbsp;many&nbsp;records&nbsp;you&nbsp;want&nbsp;returned&nbsp;and&nbsp;at&nbsp;what&nbsp;starting&nbsp;location&nbsp;you&nbsp;are&nbsp;on.&nbsp;&nbsp;In&nbsp;this&nbsp;way&nbsp;on&nbsp;the&nbsp;first&nbsp;call&nbsp;you&nbsp;create&nbsp;your&nbsp;reader&nbsp;and&nbsp;read&nbsp;100&nbsp;records&nbsp;then&nbsp;you&nbsp;return&nbsp;back&nbsp;the&nbsp;first&nbsp;100&nbsp;but&nbsp;keep&nbsp;the&nbsp;read&nbsp;in&nbsp;memory.&nbsp;&nbsp;For&nbsp;subsequent&nbsp;call&nbsp;you&nbsp;can&nbsp;go&nbsp;back&nbsp;to&nbsp;the&nbsp;reader&nbsp;and&nbsp;pick&nbsp;up&nbsp;where&nbsp;you&nbsp;left&nbsp;off.

2. Override&nbsp;the&nbsp;DrawCore&nbsp;method&nbsp;on&nbsp;your&nbsp;FeatureLayer&nbsp;and&nbsp;use&nbsp;the&nbsp;code&nbsp;below.&nbsp;&nbsp;Note&nbsp;where&nbsp;you&nbsp;see&nbsp;the&nbsp;line&nbsp;that&nbsp;has&nbsp;“FeatureSource.GetFeaturesForDrawing”&nbsp;method.&nbsp;&nbsp;You&nbsp;want&nbsp;to&nbsp;replace&nbsp;that&nbsp;with&nbsp;the&nbsp;call&nbsp;to&nbsp;your&nbsp;new&nbsp;API&nbsp;above.&nbsp;&nbsp;You&nbsp;also&nbsp;want&nbsp;to&nbsp;put&nbsp;that&nbsp;call&nbsp;in&nbsp;a&nbsp;loop&nbsp;so&nbsp;that&nbsp;you&nbsp;keep&nbsp;calling&nbsp;your&nbsp;API&nbsp;and&nbsp;then&nbsp;the&nbsp;CurrentZoomLevel.Draw&nbsp;method.&nbsp;&nbsp;The&nbsp;CurrentZoomLevel.Draw&nbsp;is&nbsp;that&nbsp;passes&nbsp;the&nbsp;data&nbsp;off&nbsp;to&nbsp;the&nbsp;styles&nbsp;for&nbsp;drawing.&nbsp;&nbsp;One&nbsp;thing&nbsp;to&nbsp;note&nbsp;is&nbsp;that&nbsp;there&nbsp;is&nbsp;a&nbsp;new&nbsp;Collection\<simpleCanidate\>&nbsp;created,&nbsp;you&nbsp;will&nbsp;want&nbsp;to&nbsp;make&nbsp;sure&nbsp;you&nbsp;move&nbsp;the&nbsp;creation&nbsp;of&nbsp;that&nbsp;BEFORE&nbsp;the&nbsp;loop&nbsp;so&nbsp;you&nbsp;keep&nbsp;the&nbsp;same&nbsp;collection.&nbsp;&nbsp;If&nbsp;you&nbsp;do&nbsp;not&nbsp;then&nbsp;labeling&nbsp;will&nbsp;not&nbsp;work&nbsp;properly.&nbsp;&nbsp;

3. Let&nbsp;it&nbsp;rip!

I&nbsp;know&nbsp;this&nbsp;is&nbsp;allot&nbsp;to&nbsp;dump&nbsp;on&nbsp;you&nbsp;and&nbsp;I&nbsp;will&nbsp;see&nbsp;if&nbsp;we&nbsp;can&nbsp;have&nbsp;a&nbsp;developer&nbsp;create&nbsp;a&nbsp;code&nbsp;community&nbsp;sample&nbsp;for&nbsp;our&nbsp;wiki&nbsp;that&nbsp;address&nbsp;this.&nbsp;&nbsp;I&nbsp;figured&nbsp;that&nbsp;as&nbsp;I&nbsp;don’t&nbsp;have&nbsp;time&nbsp;for&nbsp;that&nbsp;at&nbsp;the&nbsp;moment&nbsp;I&nbsp;would&nbsp;try&nbsp;and&nbsp;explain&nbsp;all&nbsp;I&nbsp;could&nbsp;and&nbsp;hope&nbsp;you&nbsp;are&nbsp;super&nbsp;resourceful.&nbsp;&nbsp;As&nbsp;this&nbsp;is&nbsp;key&nbsp;piece&nbsp;of&nbsp;functionality&nbsp;I&nbsp;will&nbsp;really&nbsp;push&nbsp;for&nbsp;a&nbsp;wiki&nbsp;sample&nbsp;on&nbsp;this&nbsp;as&nbsp;it&nbsp;impacts&nbsp;user&nbsp;created&nbsp;feature&nbsp;sources.&nbsp;&nbsp;One&nbsp;other&nbsp;thing&nbsp;is&nbsp;that&nbsp;there&nbsp;is&nbsp;allot&nbsp;of&nbsp;code&nbsp;that&nbsp;deals&nbsp;with&nbsp;wrapping&nbsp;below&nbsp;and&nbsp;if&nbsp;you&nbsp;do&nbsp;not&nbsp;use&nbsp;extent&nbsp;wrapping&nbsp;you&nbsp;can&nbsp;dump&nbsp;this&nbsp;code.

&nbsp;

David

&nbsp;  
` protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)        {            DrawingQuality tempDrawingQuality = canvas.DrawingQuality;            canvas.DrawingQuality = drawingQuality;            try            {                ZoomLevel currentZoomLevel = zoomLevelSet.GetZoomLevelForDrawing(canvas.CurrentWorldExtent, canvas.Width, canvas.MapUnit, canvas.Dpi);                featureSource.DrawingProgressChanged += new EventHandler<DrawingProgressChangedEventArgs>(featureSource_ProgressDrawing);                if (currentZoomLevel != null)                {                    Collection<string> columnNames = currentZoomLevel.GetRequiredColumnNames();                    RectangleShape marginWorldExtent = MarginAffectWorldExtent(canvas.CurrentWorldExtent);                    Collection<Feature> features = featureSource.GetFeaturesForDrawing(marginWorldExtent, canvas.Width, canvas.Height, columnNames);                    DrawingFeaturesEventArgs drawingFeaturesEventArgs = new DrawingFeaturesEventArgs(features);                    OnDrawingFeatures(drawingFeaturesEventArgs);                    if (features.Count != 0)                    {                        Collection<SimpleCandidate> labeledFeatures = new Collection<SimpleCandidate>();                        currentZoomLevel.Draw(canvas, features, labeledFeatures, labelsInAllLayers);                    }                    features.Clear();                    features = null;                    if (WrappingMode == WrappingMode.WrapDateline)                    {                        Collection<Feature> wrappingFeaturesLeft = FeatureSource.GetWrappingFeaturesLeft(marginWorldExtent, canvas.Width, canvas.Height, columnNames, WrappingExtent);                        if (wrappingFeaturesLeft.Count != 0)                        {                            while (canvas.CurrentWorldExtent.LowerLeftPoint.X < WrappingExtent.LowerLeftPoint.X)                            {                                canvas.CurrentWorldExtent.TranslateByOffset(WrappingExtent.Width, 0);                                currentZoomLevel.Draw(canvas, wrappingFeaturesLeft, new Collection<SimpleCandidate>(), labelsInAllLayers);                            }                        }                        Collection<Feature> wrappingFeaturesRight = FeatureSource.GetWrappingFeaturesRight(marginWorldExtent, canvas.Width, canvas.Height, columnNames, WrappingExtent);                        if (wrappingFeaturesRight.Count != 0)                        {                            while (canvas.CurrentWorldExtent.LowerRightPoint.X > WrappingExtent.LowerRightPoint.X)                            {                                canvas.CurrentWorldExtent.TranslateByOffset(-WrappingExtent.Width, 0);                                currentZoomLevel.Draw(canvas, wrappingFeaturesRight, new Collection<SimpleCandidate>(), labelsInAllLayers);                            }                        }                    }                }            }            finally            {                canvas.DrawingQuality = tempDrawingQuality;                featureSource.DrawingProgressChanged -= new EventHandler<DrawingProgressChangedEventArgs>(featureSource_ProgressDrawing);            }        }`
