ThinkGeo.com    |     Blog    |     Wiki    |     Support

Tile Caching Issues

hi Ethan,

Thanks for your response.

I wanted to be sure to let you know that these issues are intermittent. Most of the time the imagery is displayed correctly. I never once encountered these issues while testing in development. They surfaced intermittently after live deployment.

Concerning your suggested changes:

  1. In what namespace are ScaleSnapMode property and ScaleSnapMode enumeration located? I am using WmsServerEdition V9.0.0.1103 and do not see these in any namespace. Also, in what GetMapCore override should this instruction be placed? In the Handler or in the PlugIn?

  2. Indeed the ZoomLevel01 Scale that we use is 147647947. But again, this is an intermittent issue so not sure how populating TileMatrix will make a difference. However, I will make this change. There are other properties in TileMatrix such as TileHeight, TileWidth, BoundingBox, CellHeight, CellWidth. What are your recommended values for these properties?

I added the following line to the application. There is no difference that I noticed. The same cached tiles are created and the map extent renders the same, correctly.

    TheTileCache.TileMatrix     = new MapSuiteTileMatrix(147647947);

One thing nearmap pointed out to me is that when there is no tile caching the tile request size to them is always 1050x1600. However, with caching the tile size requests are all of varying values, such as 1024x1536, 768x1536, 768x1280, 512x1536, and other combinations. Why do these values vary?

What is the design consideration of having cached tile sizes all 256x256 pixels?

3-Without tile caching we have noticed on rare occasions where there might be a section of a given map extent where the imagery is not rendered, but never appears black. Only black when caching is enabled. I have already developed a service to delete tiles that have exceeded their ExpirationTime plus a few hours, so I could modify that to also delete tiles less than a certain size.

Did you determine why in the above imagery examples there are tiles that are repeating? And why are tiles zoomed so far out when they should not be? Again, remember that this does not happen on all tiles. Most of the tiles are correct.

Your thoughts are always appreciated.

Thanks,
Dennis

Hi Dennis,

Thanks for your update.

If you also cannot reproduce that in your development environment, the reason may be multi-threading.

Based on this thinking, we have to mentioned this again, I think we need your sample to try reproduce it and review code to check where is the problem.

If you cannot build the sample, please review your code to see whether you used many “static” source. If so please try your best to reduce to use it and see whether that’s helpful for solve the problem.

And our developer build a simple sample, you can try to deploy the sample and see whether it can reproduce the same problem.

WmsService.zip (2.5 MB)

Regards,

Ethan

hi Ethan,

I agree you’re correct about this being a threading issue.

The design of our WmsServer is such that it is configuration driven via web.config. All information concerning layers and anything else is verified once, upon startup, and loaded into collections. The preloaded objects contain MapConfiguration, FileBitmapTileCache, BoundingBox, GeographyUnit, CrsCollection, and other controlling properties.

Upon client request for a WmsRasterLayer the PlugIn returns the preloaded ’static’ information. The information is ‘static’ in the sense that all client requests are using the same copy of the information.

Is this the suspect ’static’ information you referred to in your response?

I emailed support@thinkgeo.com three source files that show the preload of the configuration, the use of the data by the PlugIn, and the WmsHandler. Also included is a text file with a brief description of each source code file.

Am I correct in thinking that instead of the PlugIn returning the preloaded static information it should first clone the static information and then return the cloned value?

Let me know if I’ve provided enough information. I can always send you more source files.

If you feel what I’ve outlined is the issue can you offer how to do a Deep Clone of these?

Thanks,
Dennis
OriStar Mapping, Inc.

Hi Dennis,

Thanks for your update, we had received your classes.

Our developer read your code, and think the “static clsWmsLayerActiveItem” should have problem.

In the function “GetMapConfigurationCore” of aTheWmsLayerActiveItem, you should want to always create new instance of aTheWmsLayerActiveItem.MapConfiguration instead of use the saved one. Because under multi-thread mode, you cannot make sure the property of it hadn’t get changed when it calculate the tile.

Do you think you can modify it, and please let us know whether it’s helpful.

Regards,

Ethan

hi Ethan,

Thanks for confirming the issue.

The problem for me is how to provide a new instance of MapConfiguration. It was designed this way to be efficient during the real-time request of imagery since the system is extremely busy. I don’t like the thought of recreating MapConfiguration for each invocation of GetMapConfigurationCore as this is a lot of overhead.

I don’t understand what GetMapConfigurationCore itself has to do with tiling as at this point in the processing doesn’t seem like it even knows what map extent has been requested.

Does MapSuite have any DeepClone code available for use with MapConfiguration that I can put in my application?

The more I ponder this issue I’m wondering might it not be better that MapSuite do a deep copy of MapConfiguration since it wants to change it.

Your thoughts?

Thanks,
Dennis

Hi Dennis,

I think we don’t have a deep clone for MapConfiguration for now.

And in fact you can move your logic which build the MapConfiguration into GetMapConfigurationCore. You just need to make sure each request have its own MapConfiguration, and see whether that can avoid the cache problem.

In fact build MapConfiguration shouldn’t waste too many source, and you can think it’s just a test, if it’s helpful for solve the cache problem, we can think about how to go on optimize the logic, and reduce the source usage.

Regards,

Ethan

hi Ethan,

The MapConfiguration that is created is for the layer on the Remote WMS Server so that was why I am concerned about efficiency.

I will change the design such that a new MapConfiguration is created for each request and we can see if that solves the issue.

The product is used in a very busy emergency communications center so I have to be extremely careful about introducing a new release. What is your confidence level that a new MapConfiguration for each request is the solution?

It would be great if this is the solution and then you can optimize the MapSuite design for MapConfiguration.

By the way, caching does provide for better user response and the WMS Server runs 10% more efficiently so I am very motivated to see this work.

Thanks,
Dennis

Hi Dennis,

If the server you mentioned is so important, I am not sure test on it is a good solution or not. Don’t you have another environment for test it for example a simulated server?

But if only this server can reproduce that, please let us know whether the change is helpful.

Regards,

Ethan

Hi Ethan,

There is a test server, but this is an intermittent issue and only shows up on the live system. I don’t have a method to simulate live activity. Are you having second doubts as to whether a new MapConfiguration for each request is the solution?

A few days ago I posted the following:

One thing nearmap pointed out to me is that when there is no tile caching the tile request size to them is always 1050x1680. However, with caching the tile size requests are all of varying values, such as 1024x1536, 768x1536, 768x1280, 512x1536, and other combinations. Why do these values vary?

Nearmap also sees many requests for 256x256 and this just doesn’t make sense to us.
During the initial deployment of caching I see that all the cached tiles are 256x256. What is the design consideration of having cached tile sizes all 256x256 pixels? This seems inefficient when the client size is 1050x1680.

Even after setting TileMatrix.TileHeight=1050 and TileMatrix.TileWidth=1680 the cached tiles were still 256x256. How do we get the tiles sizes to be 1050x1680 with caching?

Here’s another concerning thing I’ve noticed – for just one map extent a bit less then 1050x1680 results in eight tile cache directories being created with each directory containing twelve 256x256 pixel tiles. This seems odd to me that there are that many directories/files created for just one map extent. Below are examples.

I’ve experimented with implementing a DeepCopy. Below is code that I am using. It appears to work, but events are not copied. I lose the SendingWebRequest and SentWebRequest events. I can easily add code to set those after the DeepCopy. My question for you is does MapSuite have any events that it sets in MapConfiguration? I want to make sure I’m not losing those.

Can you speak to the above as these have to be considered before caching is deployed?

Thanks,
Dennis

    public static T DeepCopy<T>(T obj)
    {
        T result = default(T);

        using (var memoryStream = new MemoryStream())
        {
            var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            formatter.Serialize(memoryStream, obj);

            memoryStream.Seek(0, SeekOrigin.Begin);

            result = (T)formatter.Deserialize(memoryStream);

            memoryStream.Close();
        }

        return result;
    }

Hi Dennis,

For 256x256, in fact it can be think about it’s the default value of many tile provider, please view the image as below:

The Orange area is your map, the black rectangle is the tile image. You can see when you pan or zoom, your cached image cannot always suitable your map extent, so we need to combine the tile images, and draw the map on current extent. But it also will waste some areas which you can found not included in the orange area, we still need draw them but they won’t be shown on map. So the 256 value is a balance value, you can also modify it to 512 x 512 or 1024 x 1024. But set it to a big value or set is not equal square is not good solution.

And for our cache system, the 2256.99444 is the scale value, the sub folder of it and the image name of it is column number and row number. When you cached more and more areas, the image number will keep increase till all the images in this row get cached.

And it looks the MapConfiguration class don’t have event related with it.

Wish that’s helpful.

Regards,

Ethan

hi Ethan,

Thanks for your diagram and description of how your tile caching works. You mention that the 256x256 size can be changed, but you don’t mention how to change it. Would you provide a code snippet that shows in what class these properties are set so that I might experiment with the effects of alternate values?

The issue with this 256x256 approach is that MapSuite is sending 256x256 requests to our Remote WMS Server, which is woefully inefficient. It would be much more efficient, from our perspective, if you requested one large tile and then broke the large tile into smaller 256x256 tiles. Is this something that MapSuite supports?

In my last post I had asked “Are you having second doubts as to whether a new MapConfiguration for each request is the solution?”. What is your feeling now?

Thanks,
Dennis

Hi Dennis,

Our developer double check the process today, if you want to reduce the request number to remote server(not your bridge server), you just need to make your client side pass bigger boundingbox.

The bridge server will handle the boundingbox, expand it to suitable cells, find which parts is not cached local, and then sent request to remote server. After get the result, it will find missed parts tiles, and save them, and return the result to your client side.

So you just need keep the tile size of 256x256 in your bridge server cache, and add the request size from client side.

Please try it.

Regards,

Ethan

Hi Ethan,

My client side already has a request size of 1050x1680.

The Nearmap server is getting requests from the Local WMS Server for 256x256. In fact I have a spreadsheet from them that is a log of requests. I have emailed the spreadsheet to support @thinkgeo.com. Are the requests sizes what you would be expecting to see?

How is the 256x256 changed on the local WMS Server as you mentioned in your previous post.

Please remember that without caching enabled the request to the Nearmap server is always 1050x1680 corresponding to the request from the client.

Thanks,
Dennis

Hi Dennis,

Thanks for your update, our developer is working for research deeper about it.

Any update or question I will let you know.

Regards,

Ethan

Hi Dennis,

Our developer did more test, and we think they are not all the 256 x 256 tile size, but also some other tile size for example 256 x 512, 256 x 1024, 512 x 1024 etc.

The reason of that is because we saved tile local as 256 x 256, but if not all the tiles(256 x 256) included in current extent is cached, our logic will build a new bounding box include all uncached tiles, and sent one request.

That means we still only sent one request when it receive one request.

The only situation it don’t sent request is all tiles include in current extent had been cached.

So please don’t worry about it.

Regards,

Ethan

hi Ethan,

Your explanation of the requested size makes sense, thanks for that explanation.

I attempted to use the MapConfiguration.Layers[x].CloneDeep() method and found that it works while in the Visual Studio debugger, but does not work when the application is run under IIS. The DeepCopy that I wrote also works in Visual Studio debugger and somewhat works under IIS, but not 100%.

After running in the debugger I was remined that the WmsLayerPlugin.GetMapConfigurationCore is invoked only for the very first map extent request amongst all clients. Once that first request has completed GetMapConfigurationCore is never invoked again. No matter how many clients, after the first client, GetMapConfigurationCore is never invoked again. This is because all the clients use the same layer.

At this stage I don’t believe that creating MapConfiguration for each invocation is the solution.

On the first map extent request GetMapConfigurationCore is typically invoked 2-4 times depending on the requested size. Once that first map extent has been processed GetMapConfigurationCore is never invoked again.

So at most there would only be 2-4 individual MapConfiguration objects created. Do you still feel this is the issue?

What I am going to do as the next step is to create MapConfiguration entirely from the original information (no cloning) for each of the 2-4 invocations of GetMapConfigurationCore.

Have you done any more investigation of WmsServerEdition to determine where this problem might be?

One other item is that the clients have their WmsRasterLayer to use JPEG format. On implementation of caching I did not set FileBitmapTileCache.ImageFormat to JPEG so it defaulted to PNG. This meant that there must have been conversion between JPEG and PNG going on for each request. Could this possibly have caused the issue?

Thanks,
Dennis

Hi Dennis,

Our developer don’t have more suggestion about it.

We checked the sample code from your email, and our code, it looks this is the only possible reason which will make tile size looks so strange under multi-thread environment. Other part of the code won’t have problem.

And I think convert from JPEG to PNG won’t cause tile cache problem, it only need takes a little more machine source.

Regards,

Ethan

hi Ethan,

Thank you for the confirmation that I need to use unique MapConfiguration for each invocation of GetMapConfigurationCore. I will implement code that creates a new MapConfiguration from the original information with no cloning.

I have also changed the ImageFormat to JPEG so that it matches what is on the client.

Once this is deployed to production I will let you know the results.

Thanks,
Dennis
OriStar Mapping, Inc.

Hi Dennis,

Thanks for your update, any news please let us know.

Regards,

Ethan

hi Ethan,

Unfortunately I have to report that I continue to have issues.

I am now creating a totally new and unique MapConfiguration for each invocation of GetMapConfigurationCore.

As I stated in a previous reply it works in Visual Studio Debugger, but not when it is run under IIS. This was the same behavior when using deep cloning.

Instead of the imagery being returned it returns “WMS Server Exception See Server Trace”.

When I use a static MapConfiguration I do not get the above error.

If cached tiles are available when running with unique MapConfiguration under IIS the tiled imagery will appear, but as soon as you pan/zoom I see the above mentioned error.

Please keep in mind that when the first client requests a map extent GetMapConfigurationCore is invoked 2-4 times in order to process that map extent.

In an effort to add more tracing I subscribed to the below events. However, none of those events were fired, in or out of the debugger.

I’d like to see this issue escalated as the evidence points to an issue within the MapSuite WmsServerEdition SDK.

Regards,
Dennis

RequestedDrawing
RequestingDrawing

DrawingAttribution
DrawingProgressChanged
DrawnAttribution