ThinkGeo.com    |     Documentation    |     Premium Support

Multiple parallel tile requests processed sequentially

Hi,



We’ve configured a LayerOverlay setting property TileType = TileType.MultipleTyle with 2 MsSql2008FeatureLayer. We performed some functional tests on the browser and had the sensation that the multiple HTTP requests for images were being processed by tile_GeoResource.axd handler, sequentially. 



To  confirm that, we’ve captured some HTTP image requests with a proxy software and then tried to reply the same image requests with a tool that the software has which allows the reissue of requests multiple times. To our surprise, we’ve confirmed that as we increase the number of requests in parallel, the longer the time it takes to get the last response image but also the responses for images are being sent to the client sequentially. This means that a response to one image is only sent to the browser after the previous requested images, received by the handler cited before, are finished!? It looks like there is some kind of lock contention on the tile_GeoResource.axd which does not allows parallel processing of multiple HTTP image requests!?



For a web map system to be scalable there cannot be any kind of those issues!? We’ve tested the 5.5.0.0, 7.0.0.0 and 8.0.0.0 and the problem is transverse to all of them!?   



We also have attached the timeline of the requests made for each one of the versions. You can see the the requests and being processed sequentially!?



Is there anything we can do to avoid this? This problem is really critical because can be the major factor between a successful or a failure web map project.



Best regards,
BdaF




tg_5.png (48.8 KB)
tg_7.png (54.8 KB)
tg_8.png (60.1 KB)

BTW, we have created some stress tests for HTTP image requests (LayerOverlay) for ThinkGeo Web Edition 7.0.0.0 and tried to apply them on the ThinkGeo WebEdition 8.0.0.0.  
  
 It seems like they are not compatible.  
  
 Is there anyway to keep compatibility of HTTP image request between versions of ThinGeo Web Edition?   
  
 Best Regards, 
 BdaF

Hi BdaF, 
  
 Today I discuss this with our developers, we cannot find a workaround for that now.  
  
 Throw exception is provided by Layer of MapSuiteCore, but in WebEdition the map is designed to keep return images with 200 message, so we cannot implement that by inherit and override from HttpHandler. 
  
 I am sorry about that. 
  
 Regards, 
  
 Don

Hi BdaF, 
  
 About the HTTP image requests, I get two version image tile request url and compare them, but I found the parameter for them is the same, please see the compare as blow: 
  
 [Version 8.0] 
 localhost:56990/Samples/GettingStarted/tile_GeoResource.axd?BBOX=-180,45,-135,90&CACHEID=&CLIENTID=Map1&EXTRA=090719181918&FORMAT=image%2Fpng&HEIGHT=256&OId=HightLightDynamicOverlay&OVERLAYID=HightLightDynamicOverlay&PAGENAME=ksOJ9KUFk22f0ZqxdJ6A&SRS=EPSG%3A4326&STYLES=&WIDTH=256&ZOOM=3 
  
 [Version 7.0] 
 localhost:53697/Samples/GettingStarted/tile_GeoResource.axd?OVERLAYID=HightLightDynamicOverlay&FORMAT=image%2Fpng&CACHEID=&PAGENAME=ABJHlBkLsk6LTcw8iLkWng&STYLES=&CLIENTID=Map1&EXTRA=09072300230&SRS=EPSG%3A4326&BBOX=-180,45,-135,90&WIDTH=256&HEIGHT=256&OId=WorldMapKitOverlay&ZOOM=3 
  
  
 [Version 8.0] 
 OVERLAYID=HightLightDynamicOverlay 
 BBOX=-180,45,-135,90 
 CACHEID= 
 CLIENTID=Map1 
 EXTRA=090719181918 
 FORMAT=image%2Fpng 
 HEIGHT=256 
 WIDTH=256 
 PAGENAME=ksOJ9KUFk22f0ZqxdJ6A 
 ZOOM=3 
 OId=HightLightDynamicOverlay 
 SRS=EPSG%3A4326 
 STYLES= 
  
 [Version 7.0] 
 OVERLAYID=HightLightDynamicOverlay 
 BBOX=-180,45,-135,90 
 CACHEID= 
 CLIENTID=Map1 
 EXTRA=09072300230 
 FORMAT=image%2Fpng 
 HEIGHT=256 
 WIDTH=256 
 PAGENAME=ABJHlBkLsk6LTcw8iLkWng 
 ZOOM=3 
 OId=WorldMapKitOverlay 
 SRS=EPSG%3A4326 
 STYLES= 
  
 Regards, 
  
 Don

Hi BdaF, 
  
 I read our code about this part, it handle the request in parallel, but from the image you provide it looks sequentially. 
  
 I am not sure whether that is caused by some resource locked when render layer but I think I need some time to create an environment for reproduce and make sure the problem.  
  
 And if possible, you can have a test for render ShapeFileFeatureLayer but not MsSql2008FeatureLayer, I guess the problem caused by MsSql2008FeatureLayer but not the HttpHandler, if you have any result about that please let me know, thanks. 
  
 Regards, 
  
 Don

Hi Don,



We cannot use ShapefileFeatureLayer because we’re using MsSql2008FeatureLayer and geographic data is stored on SQL SERVER 2008. We’ve build a simple test on the server side with the following custom classes:



[Serializable]
    public class CustomMsSql2008FeatureLayer : MsSql2008FeatureLayer
    {
 
        public CustomMsSql2008FeatureLayer() : this(string.Empty, string.Empty, string.Empty, 4326) { }
        public CustomMsSql2008FeatureLayer(string connectionString, string tableName, string featureIdColumn) : this(connectionString, tableName, featureIdColumn, 4326/*, DatabaseConnectionMode.Default*/) { }       
        public CustomMsSql2008FeatureLayer(string connectionString, string tableName, string featureIdColumn, int srid) : base(connectionString, tableName, featureIdColumn,srid)
        {
          base.FeatureSource = new CustomMsSql2008FeatureSource(connectionString, tableName, featureIdColumn, srid);
 
        }
       
 
        protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
        {
            Debug.WriteLine(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss.fff”) + " Thread Entering CustomMsSql2008FeatureLayer " + Thread.CurrentThread.ManagedThreadId);
            base.DrawCore(canvas, labelsInAllLayers);
            Debug.WriteLine(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss.fff”) + " Thread Exiting CustomMsSql2008FeatureLayer " + Thread.CurrentThread.ManagedThreadId);
        }
       
      
 
    }
 
    [Serializable]
    public class CustomMsSql2008FeatureSource : MsSql2008FeatureSource
    {
       
        public CustomMsSql2008FeatureSource()
            : base()
        {
        }
        public CustomMsSql2008FeatureSource(string connectionString, string tableName, string featureIdColumn)
            : base(connectionString, tableName, featureIdColumn, 4326)
        {
        }
        public CustomMsSql2008FeatureSource(string connectionString, string tableName, string featureIdColumn, int srid)
            : base(connectionString, tableName, featureIdColumn, srid)
        {
        } 
   
 
    }
 
    public class CustomLayerOverlay : LayerOverlay
    {
 
        public CustomLayerOverlay() : base()
        {
 
        }
        public CustomLayerOverlay(string id)
            : base(id)
        {
 
        }
 
        public CustomLayerOverlay(string id, bool isBaseOverlay, TileType tileType)
            : base(id,isBaseOverlay,tileType)
        {
 
        }
 
        
 
        protected override void DrawCore(GeoCanvas canvas, object nativeImage, RectangleShape canvasExtent, GeographyUnit mapUnit)
        {
            Debug.WriteLine(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss.fff”) + " Thread Entering LayerOverlay " + Thread.CurrentThread.ManagedThreadId);
 
           
            base.DrawCore(canvas, nativeImage, canvasExtent, mapUnit);
 
            Debug.WriteLine(DateTime.Now.ToString(“yyyy-MM-dd hh:mm:ss.fff”) + " Thread Exiting LayerOverlay " + Thread.CurrentThread.ManagedThreadId); 
                   }
 
       
    }





The results are:



2015-04-09 02:35:47.171 Thread Entering LayerOverlay 12
2015-04-09 02:35:47.171 Thread Entering CustomMsSql2008FeatureLayer 12
2015-04-09 02:35:47.206 Thread Entering LayerOverlay 14
2015-04-09 02:35:47.207 Thread Entering LayerOverlay 9
2015-04-09 02:35:47.239 Thread Exiting CustomMsSql2008FeatureLayer 12
2015-04-09 02:35:47.240 Thread Entering CustomMsSql2008FeatureLayer 9
2015-04-09 02:35:47.242 Thread Exiting LayerOverlay 12
2015-04-09 02:35:47.248 Thread Entering LayerOverlay 12
2015-04-09 02:35:47.266 Thread Exiting CustomMsSql2008FeatureLayer 9
2015-04-09 02:35:47.267 Thread Entering CustomMsSql2008FeatureLayer 12
2015-04-09 02:35:47.268 Thread Exiting LayerOverlay 9
2015-04-09 02:35:47.282 Thread Entering LayerOverlay 9
2015-04-09 02:35:47.321 Thread Entering LayerOverlay 13
2015-04-09 02:35:47.321 Thread Entering LayerOverlay 6
2015-04-09 02:35:47.321 Thread Entering LayerOverlay 10
2015-04-09 02:35:47.336 Thread Exiting CustomMsSql2008FeatureLayer 12
2015-04-09 02:35:47.336 Thread Entering CustomMsSql2008FeatureLayer 14
2015-04-09 02:35:47.336 Thread Exiting LayerOverlay 12
2015-04-09 02:35:47.368 Thread Entering LayerOverlay 19
2015-04-09 02:35:47.372 Thread Exiting CustomMsSql2008FeatureLayer 14
2015-04-09 02:35:47.373 Thread Entering CustomMsSql2008FeatureLayer 9
2015-04-09 02:35:47.375 Thread Exiting LayerOverlay 14
2015-04-09 02:35:47.400 Thread Exiting CustomMsSql2008FeatureLayer 9
2015-04-09 02:35:47.401 Thread Entering CustomMsSql2008FeatureLayer 10
2015-04-09 02:35:47.402 Thread Exiting LayerOverlay 9
2015-04-09 02:35:47.422 Thread Exiting CustomMsSql2008FeatureLayer 10
2015-04-09 02:35:47.422 Thread Entering CustomMsSql2008FeatureLayer 13
2015-04-09 02:35:47.422 Thread Exiting LayerOverlay 10
2015-04-09 02:35:47.437 Thread Exiting CustomMsSql2008FeatureLayer 13
2015-04-09 02:35:47.437 Thread Entering CustomMsSql2008FeatureLayer 6
2015-04-09 02:35:47.437 Thread Exiting LayerOverlay 13
2015-04-09 02:35:47.456 Thread Entering LayerOverlay 14
2015-04-09 02:35:47.454 Thread Entering LayerOverlay 9
2015-04-09 02:35:47.466 Thread Entering LayerOverlay 10
2015-04-09 02:35:47.521 Thread Entering LayerOverlay 12
2015-04-09 02:35:47.521 Thread Exiting CustomMsSql2008FeatureLayer 6
2015-04-09 02:35:47.521 Thread Entering CustomMsSql2008FeatureLayer 19
2015-04-09 02:35:47.521 Thread Exiting LayerOverlay 6
2015-04-09 02:35:47.556 Thread Entering LayerOverlay 13
2015-04-09 02:35:47.558 Thread Exiting CustomMsSql2008FeatureLayer 19
2015-04-09 02:35:47.568 Thread Entering CustomMsSql2008FeatureLayer 9
2015-04-09 02:35:47.571 Thread Exiting LayerOverlay 19
2015-04-09 02:35:47.584 Thread Entering LayerOverlay 6
2015-04-09 02:35:47.599 Thread Exiting CustomMsSql2008FeatureLayer 9
2015-04-09 02:35:47.600 Thread Entering CustomMsSql2008FeatureLayer 12
2015-04-09 02:35:47.602 Thread Exiting LayerOverlay 9
2015-04-09 02:35:47.620 Thread Entering LayerOverlay 21
2015-04-09 02:35:47.626 Thread Exiting CustomMsSql2008FeatureLayer 12
2015-04-09 02:35:47.627 Thread Entering CustomMsSql2008FeatureLayer 14
2015-04-09 02:35:47.629 Thread Exiting LayerOverlay 12
2015-04-09 02:35:47.662 Thread Exiting CustomMsSql2008FeatureLayer 14
2015-04-09 02:35:47.663 Thread Entering CustomMsSql2008FeatureLayer 10
2015-04-09 02:35:47.665 Thread Exiting LayerOverlay 14
2015-04-09 02:35:47.688 Thread Exiting CustomMsSql2008FeatureLayer 10
2015-04-09 02:35:47.689 Thread Entering CustomMsSql2008FeatureLayer 13
2015-04-09 02:35:47.692 Thread Exiting LayerOverlay 10
2015-04-09 02:35:47.707 Thread Exiting CustomMsSql2008FeatureLayer 13
2015-04-09 02:35:47.708 Thread Entering CustomMsSql2008FeatureLayer 6
2015-04-09 02:35:47.712 Thread Exiting LayerOverlay 13
2015-04-09 02:35:47.734 Thread Exiting CustomMsSql2008FeatureLayer 6
2015-04-09 02:35:47.734 Thread Entering CustomMsSql2008FeatureLayer 21
2015-04-09 02:35:47.736 Thread Exiting LayerOverlay 6
2015-04-09 02:35:47.748 Thread Exiting CustomMsSql2008FeatureLayer 21
2015-04-09 02:35:47.749 Thread Exiting LayerOverlay 21





As you can see, there’s no thread entering CustomMsSql2008FeatureLayer.DrawCore(…) method in parallel. The thread’s only enter  CustomMsSql2008FeatureLayer.DrawCore(…) after another one as exited that method. This is clearly a lock contention problem. It looks like it happens on LayerOverlay class or CustomMsSql2008FeatureLayer.



For you to reproduce this, you must create an instance of CustomLayerOverlay and CustomMsSql2008FeatureLayer.



Is there anything we can do to avoid it?



Best regards,

BdaF

Hi BdaF, 
  
 Thanks for your code, it is helpful. 
  
 I cannot make sure where is the problem, today I haven’t enough time solve it, I will go on working for it and let you know if any progress. 
  
 Regards, 
  
 Don

Hi BdaF,  
  
 It looks a little more complex than I thought. 
  
 The lock is for protected thread safety, for example, each tile need request same source, so we need lock the layer when one thread access it. 
  
 Here is a simple way to remove the lock: 
  
 
 public class CustomMsSql2008FeatureLayer : MsSql2008FeatureLayer
        {
   protected override ThreadSafetyLevel GetThreadSafetyLevelCore()
            {
                return ThreadSafetyLevel.Safe;
            }
        }


 
 
  
 But if you set this, the tiles shows many different exception, that means for avoid them, you need override more functions. 
  
 I will go on look into this problem for find a better solution for this requirement. 
  
 Regards, 
  
 Don