I am considering different architectures for a system that will ideally use client-side rendering for point features and must be plugin-free. I have been using this application developed in response to this question to test my laptop (which is quite capable - quad-core 2.6 ghz cpu, 4 gb memory, not under any other load, Firefox 8) with different numbers of points in OpenLayers and it is noticeably lagging at 500 and starts struggling over 1,000. The randomly-generated features don't seem to have any event handlers and all use the same symbology.

I expect to be showing up to 1,000 features, with up to 10 different symbols, all with click and mouse-over handlers, and on less capable platforms.

I was hoping for better client-side performance, especially after seeing this GIS Cloud example - I know it works differently (HTML5 canvas vs. SVG) but the difference in performance is really striking.

My key questions (if you would be so kind) are:

  1. Is the random point generating application representative of performance in other OpenLayers applications you have written / used?
  2. Is there a proven and free alternative web mapping API that supports WMS services (which I need to use) and is faster with client-side features, without using Flash / Silverlight / any other plugins?
  3. Any other suggestions on what I should be investigating?

Relying primarily on server-side rendering is an option but both I and the client would like to avoid this due to concerns over scaling-up user numbers and the responsiveness of the UI.

  • On my 5 year old dual core, 3gb RAM desktop using that app on Firefox 8 (while downloading a 1gb Linux distro ISO), 1,000 points draw pretty much instantly, no struggling... 10,000 takes about 1.5 sec.
    – user2856
    Jan 7 '12 at 21:05
  • @LukePinner is that just drawing quickly *and panning / zooming smoothly? Retrieving data and drawing the features is fine for me too, but it's the map interaction that's the problem.
    – tomfumb
    Jan 8 '12 at 3:14
  • I just tried your app on my ipad2 and it handled 1000 points very well. With 10K points it takes a couple of seconds to render initially, but then it copes pretty well. If you want you can always subclass the OL Vector layer class and implement a custom one. I can point you to one example.
    – unicoletti
    Jan 8 '12 at 11:03
  • Yes, no problems panning/zooming. 1K points does slow down quite a bit on my 1.6ghz Atom netbook though :)
    – user2856
    Jan 8 '12 at 19:58

Answer to 1st question is Yes. You're using OL with a pretty much common configuration. There are tricks you can use to improve performance, I'll get to that later.

Answer to question 2 is maybe (especially with regards to fastness). You can search this site for a list of alternatives (one that springs to mind right now is Leaflet).

Answer to question 3: start with measuring:

I edited a local copy of the app so that the renderer is explicitly specified in the option list for the Vector layer. During the tests I would omit the Canvas renderer and then reload the page the experiment with a different one:

var pts = new OpenLayers.Layer.Vector("Points", {renderers: ["Canvas", "SVG", "VML"]});

I added a timer to the redraw function so that it prints out how much time it spent drawing:

function redraw() {
var start = (new Date).getTime();
var diff = (new Date).getTime() - start;
console.log("redraw completed in "+diff+"ms");

After that I tried several runs on both Chrome 17 and Firefox 8.0.1 on OSX SL drawing 1000 and 5000 features. To my surprise the SVG renderer is in average 20% faster than the Canvas renderer! (Note: on Windows js time is not as precise as in OSX so the results could be less consistent).

This and your telling that

it's the map interaction that's the problem

, IMHO, tells us that the hotspot is in the Vector handling of features. While working on an app of mine, I recently took a look at it and decided to subclass it and then rid it of all the complicated code that's of no use for simple points. Admittedly I went pretty wild and even removed the dependency on OpenLayers.Geometry.Point and my version now works on simple js objects with x,y attributes.

Your options are, in desc order of benefit/cost:

First option is to filter the visible points server-side by configuring a strategy option to the vector layer like the following:

 strategies: [new OpenLayers.Strategy.Refresh({force:true}), new OpenLayers.Strategy.BBOX({ratio:2, resFactor: 3})],

This way when you zoom in the number of features drawn client side will be limited to those visibile at that extent, instead of all.

As second option you might consider writing a customized Vector/Renderer. An example of a custom, stripped down, faster implementation is available on my github page here. While not suitable for all uses it should be enough to give a rough idea of what I'm suggesting.

Third option for when the user is fully zoomed out is to implement some kind of server-side clustering of features so that close points are merged into a single one, again reducing the number of features drawn.

  • Many thanks for the detailed and thorough response. I will very likely be looking at server-side clustering, hopefully in combination with a caching strategy so that the operation only occurs when necessary. One of the options for server-side is MapGuide, so the approach for retrieving and clustering points could be totally custom. I will also have a play around with the renderer options to see what difference it makes.
    – tomfumb
    Jan 9 '12 at 0:01
  • 1
    I have added a link to an example vector/canvas renderee that I use in a proj of mine.
    – unicoletti
    Jan 10 '12 at 9:55
  • Wow the stripped-down example makes a massive difference, that's really impressive. I went from struggling with 1,000 features to flying with 10,000
    – tomfumb
    Jan 10 '12 at 16:16
  • I modified the first example (swingley.appspot.com) to use the OL Canvas renderer and a solid fill for points, and the zoom and pan performance is actually very similar to your TagCanvas & TagVector. I also re-implemented the hit-test functionality you removed in your modifications so I could test the comparative performance - the Tag* approach was approxomately 20% faster at identifying which feature was hit (out of 5000). Given the significant effort in writing / updating the custom classes, and the similar performance (in my tests), I think I'll see what vanilla OL can do
    – tomfumb
    Jan 22 '12 at 7:35
  • That's because hit-test redraws all features into another canvas, thus they're drawn twice with each refresh.
    – unicoletti
    Jan 22 '12 at 17:00

Using UTFGrid and TileMill you can display unlimited points with pretty good performance. Displaying n random points is kind of a contrived example that wouldn't work in that situation or with GISCloud or any similar magic, though - since vector performance hacks usually require knowledge of the full dataset and some pre-processing: both TileMill and GISCloud do a lot of tiling.

Not the answer you're looking for? Browse other questions tagged or ask your own question.