ThinkGeo.com    |     Documentation    |     Premium Support

InMemoryFeatureLayer Refresh

I am maintaining an InMemoryFeatureLayer to render dynamic points.  The functionality is working fine except that it takes too long for the Overlay to refresh.  It would appear that the entire Overlay, and hence all points, are being refreshed.


The application has a high rate of data to process and it appears that the refresh of the Overlay cannot keep up.  Ideally, instead of refreshing the entire Overlay I would like to refresh only those icons on the map that are new or have changed position.


One of the symptoms that I see are semi-transparent red-colored tiles appearing/disappearing, which have a bold red X in the middle.


I trap DrawnExceptions and receive quite a few as shown below.


I currently use EditTools to insert/update/delete the features of the layer.  For more efficiency I am going to change from using EditTools to InternalFeatures.


Does MapSuite provide the ability to refresh only those InMemoryFeatureLayer features that have changed?


Regards,


Dennis


 


DrawnExceptions


Message=Cannot insert items into an STR packed R-tree after it has been built.


Message=Destination array was not long enough. Check destIndex and length, and the array's lower bounds.


Message=Collection was modified; enumeration operation may not execute.


Message=The FeatureSource is not open.   Please call the Open method before calling this method.


 


 


 



Hello Dennis, 
  
 Thanks for your post, I saw that you got exception “Cannot insert items into an STR packed R-tree after it has been built”, there are some possibility like multithread, but also there is a known issue will cause this when commit the transaction, we have fixed that before, could you please upgrade to the newest dlls version and have a try? 
  
 “Does MapSuite provide the ability to refresh only those InMemoryFeatureLayer features that have changed?” 
  
 Sorry we don’t support do that, layer is the minimum level must be refreshed. And for the performance your mentioned, I think it depends on how many points you want to display in the map in same time, if it’s too many, the render speed will slow down. 
  
 Here is a suggestion for improve the performance: Use the zoomlevel style to control how many points will be render in the same time if it’s possible, like some points only display from zoomlevel01-zoomlevle05, some display from 06-10. 
  
 Let us know your queries. 
  
 Regards, 
  
 Gary

 Posted By Gary on 09-17-2012 03:49 PM 

 I saw that you got exception “Cannot insert items into an STR packed R-tree after it has been built”, there are some possibility like multithread, but also there is a known issue will cause this when commit the transaction, we have fixed that before, could you please upgrade to the newest dlls version and have a try? 




  Hi Gary, 


Do you remember at what version did you fix it? This is kind of same exception I was having in Ticket 7357


Carlos



Hello Carlos, 
  
 I appreciate your information, after I check ticket 7357, I just realized we meet this issue but we didn’t fix it, so there is just one reason will cause this, multithread. 
  
 Dennis, 
  
 I made a mistake that tell you to try the newest dlls, for your situation, it’s because more than two threads are trying to commit the transaction, and in this action, it will built a R-tree which are unique after built, so it throw this exception. Please use the lock to resolve this problem. 
  
 My apologize. 
  
 Gary

Gary,


Thank you for the tips.  I had thought I was single threaded updating the layer, but in fact was not.  I implemented a queue and now do not received any DrawnExceptions.  My points are now moving around nicely on the map.


I do still have a concern about the fact that the entire layer is refreshed as opposed to only those points that have changed.  One thing I do to minimize refreshes is to only do a refresh if the point is within the CurrentExtent.


I do not have total control over how many points to display as if a point comes in it must be added to the layer.  Even at the highest extent I might have 20-30 points.  I do limit though the minimum extent at which any points are displayed.


My application receives a high rate of dynamic add/update/delete of points so I am looking for the most efficient and best way to update/refresh this layer.


Does ThinkGeo have any plans to provide a 'refresh by point' capability in upcoming releases?


Regards,


Dennis


 



 Hello Dennis,


 
 Thanks for the further information, sorry as I know we don't have an plan about this, but you can vote this enhancement to helpdesk.thinkgeo.com/EnhancementTracker. This captures the enhancement request and provides visibility to the customer letting them know that the enhancement is on a list somewhere and that popularity of the enhancement helps set the priority of when the enhancement would be added to the product. This option doesn't carry any cost for you. 
  
 Or if you need this function immediately, your account rep can contact you for a professional services. 
 
 Also I noticed you said you might only  have 20-30 points in one levels, though I don't know how many points you will have in more levels in same time, but if it's not over thousands, it won't cause performance problem.
 
 But you said you did queue job, so is that possible the time cost from the queue? Could you please check the LayerOverlay.DrawingTime property and see what's the time cost?
 
 Regards,
 
 Gary
  

Gary,


I am continuing to have issues with the drawing of the InMemoryFeatureLayer, but have made some progress.


My Overlay Refresh rate for the description that follows is once a second done once all the updates queued for that second have been updated within the layer.


When I have more than roughly 75-100 points within view the DrawnExceptions appear.  I added code to trap the DrawingTime and found it to be runing around 45 milliseconds, which does not seem horrible to me.  What exactly is DrawingTime measuring?


When there are 100+ points within view the updating is erratic.  Sometimes the label backgrounds will not draw, only the foreground, many times whole sections(tiles) of the layer will disappear from view and then reappear.


I have 1200+ point features total within the layer.  Updates to those points are coming in at the rate of 20+- per second.


The problems do not stem from how many total features are in the layer, but rather how many features are currently in-view.


CPU usage is also high, when there are 100+ features within view, running approximately 30-45%.  This seems high and would not want the CPU to run at that rate for an extended period.


My concern is that the entire Overlay is being drawn instead of just the areas which have changed.  This has to add extra over-head to updating the UI.


Another concern is threading.  When a Refresh is invoked is that performed in the thread in which it is invoked or is that done on another thread?  This is the only reason that I can think of as to why I might be getting DrawnExceptions.


Based on my suspicions concerning threading I changed the Overlay Refresh interval to 2 seconds.  The refresh is done only once all the queued feature updates have been applied to the layer.  With a two second refresh interval 200-300 in-view features can now be handled without any DrawnExceptions.


Based on changing the interval from one to two seconds I believe that any updating of features in the layer will interfere with an Overlay Refresh causing DrawnExceptions.  This would only happen in a heavily loaded system.  With the two second interval the Overlay Refresh now has time to finish before the next set of queued feature updates are processed


The CPU runs between 0-45% with a tw-second interval, which I believe is still too high.


Are there any plans in the near future to change MapSuite so that the interference between feature update and layer refresh is handled entirely behind-the-scenes within MapSuite?


Regards,


Dennis


 



Hello Dennis, 
  
 For drawingtime property, we track the drawing time for the layer and report it back in this method. This is useful for determining the speed of various layers. So if the drawingtime is not very long, the performance reason is not the map control draw the features, like in your scenario, the drawing time is 45 milliseconds, so it’s really fast. 
  
 You can keep tracking this time to know how much time the drawing cost when you have more than 1000+ points. 
  
 Also I think a easier way to find out the root cause for this problem is provide a self-contained sample to us, if we can recreate your problem, we can resolve it quickly. 
  
 Regards, 
  
 Gary

Gary,


Thanks again for responding.


I'm afraid I am at a loss as to how to properly implement the Refresh of my InMemoryFeatureLayer.  It would be difficult to provide you with a self-contained example of my code as there are so many pieces to the project.  And the most important piece is actually the real-time data feed.  Might we try to get to the bottom of this with conversations?


I've done some tests and find that the problem is with Refresh of the Overlay that contains the layer.  I removed the Refresh entirely from the code and find that the application uses on average 1% of the CPU and there are no DrawnExceptions since I'm not doing any refreshes.  I am confident that the code that uses the EditTools to update the layer is operating properly.


When I put the Refresh back in I continue to have pink tiles appear, many DrawnExceptions, and whole sections of the layer disappear and then reappear.  Many of the labels are also drawn without the background mask.


In previous conversations on this thread it was mentioned that threading is the only thing that causes DrawnExceptions.  So I have to ask how and in what thread is the Refresh to be invoked?  I am invoking it in the same thread that I am invoking the EditTools in order to update the features.


In my prior response to you I mentioned that as long as I wait a sufficient amount of time for the Refresh to complete before I allow further invocations of the EditTools I do not get DrawnExceptions, but that time is at least two seconds and more, which I find unacceptable.


It appears to me that a Refresh is not a synchronous method, but rather asynchronous.  Is that true?  I say that because even though my EditTools and Refresh are invoked on the same thread I continue to experience DrawnExceptions.  And my requests to update the layer via EditTools and request to Refresh are single threaded thru the use of a locked queue.


Would it be advisible to make use of the Drawing & Drawn Events?  Do not invoke EditTools from the time the Drawing Event is invoked until the Drawn Event is invoked.  Once the Drawn Event is invoked then proceed with updating of features with EditTools.


What advice can you offer in terms of how to consume large amounts of requests to update the layer and then invoke a Refresh?


Please remember that my application is receiving a very large number of update requests every second, somewhere on the order of 20-30 per second.  And this is continuous, there is no let up on the requests.  In order to be efficient I also do not do a Refresh unless the feature being updated is within the currently viewed extent.


Your help is appreciated.


Dennis


 


 



Gary,


I've done some additional work on this and decided to trap the Overlay Drawing and Drawn Events.  I then calculated the time difference between the two events which I believe is the actual time it takes to Refresh the Overlay.  Depending on how many features are in the current extent the actual time it takes to Refresh is anywhere from 0 to 11 seconds.  Zero being when none or just a few features are within the current extent and 11 seconds when there roughly 500 features within the current extent.


I've also changed my code so that no features are updated during the time from the Overlay Drawing to Drawn event.  This technique always guarantees that I will not experience any DrawnExceptions.


My conclusion is that the features may not be updated while a Refresh is still in-progress, otherwise DrawnExceptions will be experienced resulting in transparent pink tiles and partially drawn Overlay.


Does MapSuite have any plans to allow feature updates to take place while a Refresh is in-progress?


Dennis


 



Hi Dennis, 
  
 Did you try to protect the updating block of code with a synclock structure?

Carlos,


 


Yes, have impleneted locking around the EditTools updating and Refresh.


The issue is that the Refresh is an asynchronous operation as opposed to synchronous.


My application works fine with my current design.  The iusse I have now is that the Refresh of the Overlay takes much too much time.  The only way to solve this issue is for MapSuite to provide a means to Refresh only selected sections(tiles) of the Overlay as opposed to a Refresh of the entire Overlay.  In high message systems a Refresh of the entire Overlay is simply too time consuming.  There should be a Refresh that refreshes only the tiles that have changed.


Is there a means whereby MapSuite will only Refresh what has changed?


Regards,


Dennis


 



Dennis, 
  
   Knowing what has changed has cost associated to it as well.  I could see adding a refresh overload that worked with a rectangle that you passed in.  Do you know what changed?  What if you were to provide a rectangle region of what to refresh then we figure out what tiles those are and just refresh things in those tiles? 
  
 David

David,

Yes,I do know what has changed. I know when a feature has been added, deleted, changed, and moved from one point to another.

So I would like to take advantage of selective refresh of the overlay.

I you have some sample code that would be appreciated.

My application is going to have to be as efficient as possible because my message traffic is going to potentially triple.

Thanks,
Dennis

Hi Dennis,  
  
 This is a great idea! We don’t have any resources available until after next week to investigate but this would be great feature to implement. I will get back with you when we have something workable.

Ryan,


That is great news.  I'll look forward to making use of a selective refresh feature.


Dennis