ThinkGeo.com    |     Documentation    |     Premium Support

Change some of the implementation of the Feature object

In learning how to use the ThinkGeo controls for our application I ran  across a need to override some of the functionality of the Feature.

However  I found that the Feature is not an object but a struct which can not be  derived from. My question or suggestion would it be possible to make  this a class or an Interface so that we could change some of the  implementation to better suite what we are trying to do.



The main reason for this is to help increase the performance of the  GetShape method. I would like to be able to cache the shape once it is  created instead of having to recreate it every time the method is being  called.



Thanks

Rick Jones



Rick, 
  
   The feature is a struct so that the memory can be easily reclaimed without allot of pressure on the garbage collector.  Since each pan or zoom of the map create lots of features having them as classes caused some memory issues in the past.  We have thought about combining features and shapes into some kind of single unit that was a class with arrays of structures as the points however this is a bit complex to do while the API is live, meaning having to maintain backwards compatibility.   
  
 We do have a Tag property that is type object, you could place the shape in there and retrieve it that way.  I would create an extension method like GetShapeEx and in that method you can check the tag first and if it doesn’t exist then call the normal GetShape and then cache it in the tag.  In that way it’s convenient, gets what you want, and looks like it was always part of the class.  This is also helpful if you are already using the tag for something else as you can add a collection of stuff to store in the tag and use the extension methods to make nice accessors for them. 
  
 David 
  
 David

Thanks for the prompt reply,


Sorry i am late in responding, i ended up having to travel for another project.


 


I understand the use of the stuct to help with the GC.


What if you added a Func<string,BaseShape> property ie


Func<string,BaseShape> UserSuppliedShape{get;set;}


 


then in the GetShape() method


you could do something like this


    public BaseShape GetShape( )

        {

            if ( UserSuppliedShape != null )

            {

                return UserSuppliedShape( id );

            }

            return BaseShape.CreateShapeFromWellKnownData( this.shapeArray );

        }


You would still retain the struct, but at the same time allow people to provide the shape to use. This would allow for caching of frequently used shapes across web sessions. I could have a ShapeProvider that would provide cached shapes and not have to recreate the shapes for every web session.


You could also use the approach for any of the other methods that need to work with creating objects from the byte[] like bounding rect etc...


Just an idea.


Looking for ways to speed up the creation of the maps.


 


 



Rick, 
  
   I understand the method above except that it would require is to add a bunch of properties, backed by fields, that would facilitate the caching.  In our design structure needs to be as small as possible otherwise we use too much memory and it gets inefficient to keep copying the memory over and over.  Why are you converting features to shapes often, typically in the drawing cycle we are able to go from file to screen without every converting features to shapes.  Maybe we can help with a down stream optimization. 
  
 David

David,


First let me claify, we are not converting features to shapes, and we are not using shape files from teh disk, we have stored the shape data into an array field in the db (RavenDB) we are using and have created our own featuresource and feature layer to provide the data we need based on the users request.


I was looking at the feature code and saw the call to GetShape() that takes the memory buffer and creates the BaseShape.CreateShapeFromWellKnownData(). every time. What I would like to do is cache the result of the CreateShapeFromWellKnownData to cut down the amount of memeory required if we have a large load on the web server. I dont want to have to copy the same array of bytes for the same shapes to every session. To me it would be better to store the shape that the GetShape() method in the feature returns, instead of copying the array of bytes for the WellKnownData. 


I also dont see how it would require adding serveral properties, I just see adding one, the Func<BaseShape,string>. 


Maybe I am missing something that is already doing the caching independent of the session, if so just let me know. 


Or is there a way to cache the features/images on the client by using some java script so we dont have to make round trips to the server when the user pans or zooms?.


 


 


Thanks for replys.


Rick


 


 



Rick, 
  
   This sheds quite a bit more light on what you are worried about and what you are doing, thanks for that.  On the server side when a tiles is going to be drawn, the data is queried from the source, typically in well know binary, and it stays in well known binary for the rest of it’s life until drawn.  The only exception is if you do some operation to convert it to a shape.  In the normal drawing process it never becomes a shape.  After the tile is drawn for that request the memory is releases.  The features should no persist on the web server between requests, thereby not duplicating the memory long term.  Of course you could have two users making two requests for the same area and that could be loaded in memory twice for a short period of time.  
  
   Once the tile is drawn it is typically cached to disk on the server, if you have the tile cache turned on, and it is by default cached on the client as a image tile.  This means as you pan to areas you have already been there is at least one level of caching and possibly a second.  This cuts the load on the server quite a bit of you manage the tile caches well.  The client side caching is controlled by LayerOverlay.ClientCache property, check the defaults.  For the server side caching it is in the LayerOverlay.ServerCache.  The CacheId on these are just unique strings that you can change when the style changes.  For example if the maps are static then you can keep the same ID between session and between users and they will all pull from the same place.  Once a user re-styles the map you can set a random CacheId and that will cache that data separately. 
  
   I hope this helps, if you need more information I would be happy to setup a Skype call for early next week and I can get more details.  This way we can go back and forth quickly and I can hear all of your concerns and ideas. 
  
 David