Handling Large Amounts of Markers in Google Maps
To use markers in Google Maps is fairly trivial, at least when you have a reasonable amount of them. But once you have more than a few hundred of them, performance quickly starts to degrade. In this article I will show you a few approaches to speed up performance. I’ve also put together a test page to compare them.
Update [2009-05-06]:This article has been updated with the addition of the utility library MarkerClusterer. The test results in the end of the article and the test page has also been revised.
If you’re new to markers in Google Maps I recommend that you first read Basic operations with markers in Google Maps for an introduction on how to use them.
The Marker Manager – Keeps track of them
Your first option might be to use the MarkerManager since it’s an utility library provided by Google. Rather than adding each marker individually to the map using GMap2.addOverlay() you first add them to the MarkerManager. The MarkerManager keeps track of all your markers. By defining at which zoom-levels each marker should appear you can cluster the markers to reduce the amount being shown at a time.
The MarkerManager is initially a bit slower than just adding markers directly to the map but the added benefit is that you can have more control over them.
You add markers to the MarkerManager with addMarker(GMarker, minZoom, maxZoom?). This method takes three arguments, the first one being the marker you want to add. The two second arguments are optional but define at which zoom-levels the marker will be visible.
A simple example
// Create a new map
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(59.5, 14.0), 6);
// Create a new instance of the MarkerManager
var mgr = new MarkerManager(map);
// Create a new marker
var marker = new GMarker(new GLatLng(59.0, 13.80));
// Add marker to the MarkerManager
mgr.addMarker(marker);
Obviously there’s not much use adding a single marker to the MarkerManager, but if you have hundreds of them, this might be the way to go.
Bulk adding the markers
An even more efficient way of using the MarkerManager is to do a bulk add by first putting all your markers into an array and then add the array to the MarkerManager with the addMarkers(markerArray, minZoom, maxZoom?) method.
// Create a new instance of the MarkerManager
var mgr = new MarkerManager(map);
// Create marker array
var markers = [];
// Loop to create markers and adding them to the MarkerManager
for(var i = 0; i < 50; i += 0.1) {
var marker = new GMarker(new GLatLng(59.0 + i, 13.80 + i));
markers.push(marker);
}
// Add the array to the MarkerManager
mgr.addMarkers(markers);
// Refresh the MarkerManager to make the markers appear on the map
mgr.refresh();
Notice that you have to use mgr.refresh() after adding the marker array to it. That's not necessary when adding the markers one by one.
Additional methods
- removeMarker(marker)
Removes a marker from the MarkerManager - clearMarkers()
Removes all markers. - getMarkerCount(zoom)
Returns the number of markers at a given zoom-level.
The MarkerManager is a utility library provided by Google. On the URL below you'll find the source code as well as the full documentation and examples.
Marker Light - Markers on a diet
Pamela Fox at Google has made a sample app for what she calls MarkerLight, which render less complex markers, thus increasing performance. The trade-off is that it's really just an image on the map, you can't interact with it. If you don't have the need for interaction this is a really easy way to gain performance, the only difference from the ordinary way of doing it is that you create a MarkerLight instead of a GMarker.
On Pamelas post about MarkerLight she explains why this approach is faster:
The reason GMarker takes so long is that it's actually composed of many DOM elements - foreground, shadow, printable version, clickable area, etc.
If your purpose is visualization, then you can get away with just creating a GOverlay extension like MarkerLight that creates a div with a background URL (or background color, even better!).
- Pamela Fox
Here's how to use it:
map.addOverlay(new MarkerLight(latlng, {image: "red_dot.png"}));
red_dot.png in is the image used for the marker. It's a very small and simple one.
You can try performance with different numbers of markers on Pamelas test page.
Using Marker Light in combination with MarkerManager
You can add the benefits of MarkerLight with the clustering capabilities of the MarkerManager. It's really easy, just combine the two:
mgr.addMarker(new MarkerLight(latlng, {image: "red_dot.png"}));
The reason you should do this is that you can display a different number of markers at different zoom levels. This way you can ensure that not too many markers are displayed at the same time.
Clusterer - Only show what you need
A different approach is to use ACME labs Clusterer. It's a third party library that offers a faster way of adding markers. It's released under the BSD license and is freely available.
It allows faster performance by doing two things.
- Only the markers currently visible actually get created.
- If too many markers would be visible, then they are grouped together into cluster markers.
This lets you have literally thousands of markers on a map while maintaining decent performance. My tests with this approach shows that it's significantly faster than the MarkerManager approach.
Here's how to use it:
// Create a Clusterer object
var clusterer = new Clusterer(map);
// Create marker
var marker = new GMarker(new GLatLng(57.8, 14.0));
// Add marker to the map
clusterer.AddMarker(marker, 'text to infobox');
To remove a marker from the map call clusterer.RemoveMarker(marker).
There's also a few methods to change the behavior of the marker.
- clusterer.SetIcon(GIcon)
Changes the cluster icon - clusterer.SetMaxVisibleMarkers(n)
Sets the threshold marker count where clustering kicks in. Default value is 150. - clusterer.SetMinMarkersPerCluster(n)
Sets the minumum number of markers for a cluster. Default value is 5. - clusterer.SetMaxLinesPerInfoBox(n)
Sets the maximum number of lines in an info box. Default value is 10.
ClusterMarker - Chunk 'em all up
ClusterMarker is a free Javascript library released under the GNU General Public License, that adds clustering capabilities to markers. The unique thing with this library is that it automatically detects markers that intersect each other and cluster these into a single cluster marker.
The images below illustrates how this works
The constructor takes two arguments and looks like this:
var cluster = new ClusterMarker(map, options)
map is a reference to the map object and options is an object literal that can have these properties:
- clusterMarkerIcon [GIcon]
Changes the default cluster marker icon to an icon of your choice.
- markers [array]
An array with all the markers you want to pass to the ClusterMarker
Apart from these properties you can also use all the other properties of the class. Se the documentation for a complete list.
Here's how to add markers using the ClusterMarker with a minimum amount of code.
var markerArray = [];
// Insert code to fill the markerArray with markers...
// Creating a new cluster by adding the map and the markerarray
var cluster = new ClusterMarker(map, {markers: markerArray});
// Refreshing to show the added markers
cluster.refresh();
This code will insert the markers on the map and cluster them under one icon if they're close enough to each other. For more fine grained control of how it operates there are several methods and properties. For a detailed explanation of how the library works there's excellent documentation on the Clustermarker Project page.
MarkerClusterer - The new kid in town
This utility library is the newest of them all and wasn't around when I originally wrote this article. This library, which is written by Xiaoxi Wu and is part of the Google Maps Open Source Utility Library is easy to use and shows excellent performance.
Like some of the other libraries it reduces the number of visible markers by clustering them together making it easier to get an overview. Watch the image below to see how.
Image by Xiaoxi Wu
It's constructor takes three arguments, the first one being a reference to the map, the second one being an array of GMarkers and the third one being an object literal with options. Only the first one is required.
var markerCluster = new MarkerClusterer(map, markers, opts);
So to add a bunch of markers to the map having the default settings of the MarkerClusterer you do this:
var markers = [];
// Insert code to fill the markerArray with markers...
// Creating a new cluster by adding the map and the array of markers
var markerCluster = new MarkerClusterer(map, markers);
See the documentation for a full explanation of the library and it's capabilities. Also read MarkerClusterer: A Solution to the Too Many Markers Problem on the Google Geo Developer blog for more information.
Compare performance
Compare the different techniques on the Test page
Inspired by Pamela Fox testpage for MarkerLight I've set up a test page of my own where you can test the performance of all the different approaches in this article.
The result
I ran a series of test with a few different browsers. In each test I added 500 markers using the different techniques. Between each test I refreshed the browsers. All tests were performed on a PC with a 3.60 GHz Pentium 4 HT processor and 2 Gb RAM running Windows XP.
| Google Chrome 1.0.154 | Safari 3.2.1 | Firefox 3.0.10 | Internet Explorer 8.0 | Opera 9.63 | Average result | |
|---|---|---|---|---|---|---|
| GMarker | 1649 | 1168 | 3020 | 3329 | 1250 | 2083 |
| MarkerManager | 1828 | 1333 | 3232 | 5485 | 1297 | 2635 |
| MarkerLight | 393 | 269 | 797 | 860 | 297 | 523 |
| MarkerManager + MarkerLight | 400 | 534 | 1134 | 906 | 469 | 689 |
| Clusterer2 | 29 | 40 | 66 | 109 | 47 | 58 |
| ClusterMarker | 432 | 502 | 832 | 1219 | 500 | 697 |
| MarkerClusterer | 189 | 527 | 374 | 1047 | 329 | 493 |
Note: Since the addition of MarkerClusterer I've ran the tests again and updated the result grid. Some of the web browsers are newer than in the lats test run. See the old test results.
In this test Clusterer2 was the fastest technique of them all. Be aware however that this is not the entire truth since I've only been able to measure how long it takes before the markers are passed to the map, not the actual time until they are visible on the map. When taking this into consideration I find that MarkerClusterer is the fastest technique closely followed by ClusterMarker.
When it comes to browsers the fastest performance is marked with green and the worst performance is marked with red in the result grid. Not surprisingly Internet Explorer is the slowest of the lot. Google Chrome and Safari has the fastest overall performance with their blazing fast Javascript engine.
If you have an idea on how to improve this test to better measure the actual time until the markers are visible on the map, please share in the comments or contact me through the Contact page.
Conclusion
The techniques showed in this article are all fairly easy to implement and works well when you don't have an incredibly large amount of markers. For those occasions where none of these techniques suffice you will have to resort to more extreme measures, like creating a big overlay with all the markers, but that's beyond the scope of this article.
I hope that you'll find these techniques helpful. Happy coding!
My Google Maps book
If you found this article useful you might be interested in my book Beginning Google Maps API 3. It covers everything you need to know to create awesome maps on your web sites. Buy it on Amazon.com

Pingback: boblog» Blogarchiv » Google Maps API
Pingback: ? Relations › links for 2009-04-27
Pingback: Marker-Cluster für die Google Map : Railslove
Pingback: Fatwallet Member Google Map
Pingback: Sidingsound » Blog Archive » Lifestream Weekly Digest – September 28th
Pingback: Google Maps » Blog Archive » Duuu?o markerów – MarkerManager
Pingback: Adjusting MarkerClusterer for Google Map « Skura BI Group Blog
Pingback: Process: Mapping War Logs for the Guardian
Pingback: Web Solutions and Design - Asteriskr
Pingback: Nouvelles cartes « Location's Blog
Pingback: Using an Access Database with Google Maps API | weblog of lindsey bell
Pingback: Google Maps API | Blog de Jaime Portuondo