Created
October 25, 2012 05:40
-
-
Save springmeyer/3950618 to your computer and use it in GitHub Desktop.
tilelive-mapnik image pool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/render.js b/lib/render.js | |
index cd74f80..dec3af2 100644 | |
--- a/lib/render.js | |
+++ b/lib/render.js | |
@@ -1,6 +1,7 @@ | |
var mapnik = require('mapnik'); | |
var _ = require('underscore'); | |
var Step = require('step'); | |
+var Pool = require('generic-pool').Pool; | |
var MapnikSource = require('./mapnik_backend'); | |
var solidCache = {}; | |
@@ -11,6 +12,53 @@ var EARTH_CIRCUMFERENCE = EARTH_DIAMETER * Math.PI; | |
var MAX_RES = EARTH_CIRCUMFERENCE / 256; | |
var ORIGIN_SHIFT = EARTH_CIRCUMFERENCE/2; | |
+var image_pools = function(size) { | |
+ return { | |
+ max: size || 5, | |
+ pools: {}, | |
+ acquire: function(id, options, callback) { | |
+ if (!this.pools[id]) { | |
+ var that = this; | |
+ this.pools[id] = Pool({ | |
+ name: id, | |
+ create: function(cb) { cb(null,new mapnik.Image(id,id)) }, | |
+ destroy: function(obj) { delete obj }, | |
+ max: that.max, | |
+ idleTimeoutMillis: options.idleTimeoutMillis || 5000, | |
+ log: false | |
+ //reapIntervalMillis | |
+ //priorityRange | |
+ }); | |
+ } | |
+ this.pools[id].acquire(callback, options.priority || 0); | |
+ }, | |
+ release: function(id, obj) { | |
+ var p = this.pools[id]; | |
+ if (p) { | |
+ p.release(obj); | |
+ if (p.waitingClientsCount() > 0) { | |
+ console.log(id + ': pool size: ' + p.getPoolSize()); | |
+ console.log(id + ': available: ' + p.availableObjectsCount()); | |
+ console.log(id + ': waiting : ' + p.waitingClientsCount()); | |
+ } | |
+ // todo - cleanup unused pool for a given id | |
+ } | |
+ }, | |
+ drain: function() { | |
+ for (obj in this.pools) { | |
+ var p = this.pools[obj]; | |
+ p.drain(function () { | |
+ p.destroyAllNow(function() { | |
+ }); | |
+ }); | |
+ }; | |
+ } | |
+ }; | |
+}; | |
+ | |
+var images = image_pools(20); | |
+//Math.ceil(Math.max(10, require('os').cpus().length * 2)) | |
+ | |
exports['calculateMetatile'] = calculateMetatile; | |
function calculateMetatile(options) { | |
@@ -119,58 +167,88 @@ MapnikSource.prototype._renderMetatile = function(options, callback) { | |
// Calculate bbox from xyz, respecting metatile settings. | |
var meta = calculateMetatile(options); | |
- | |
- // Set default options. | |
- if (options.format === 'utf') { | |
- options.layer = source._info.interactivity_layer; | |
- options.fields = source._info.interactivity_fields; | |
- options.resolution = source._uri.query.resolution; | |
- options.headers = { 'Content-Type': 'text/javascript; charset=utf-8' }; | |
- var image = new mapnik.Grid(meta.width, meta.height); | |
- } else { | |
- options.headers = { 'Content-Type': 'image/png' }; | |
- if (options.format.indexOf('jpeg') != -1) { | |
- options.headers = { 'Content-Type': 'image/jpeg' }; | |
- } | |
- var image = new mapnik.Image(meta.width, meta.height); | |
- } | |
- | |
options.scale = source._uri.query.scale; | |
- | |
// Add reference to the source allowing debug/stat reporting to be compiled. | |
options.source = source; | |
process.nextTick(function() { | |
source._pool.acquire(function(err, map) { | |
if (err) return callback(err); | |
- | |
// Begin at metatile boundary. | |
options.x = meta.x; | |
options.y = meta.y; | |
- | |
map.resize(meta.width, meta.height); | |
+ //console.log('w: ' + meta.width + " h: " + meta.height); | |
map.extent = meta.bbox; | |
- try { | |
- source._stats.render++; | |
- map.render(image, options, function(err, image) { | |
- process.nextTick(function() { | |
- // Release after the .render() callback returned | |
- // to avoid mapnik errors. | |
- source._pool.release(map); | |
+ // Set default options. | |
+ if (options.format === 'utf') { | |
+ options.layer = source._info.interactivity_layer; | |
+ options.fields = source._info.interactivity_fields; | |
+ options.resolution = source._uri.query.resolution; | |
+ options.headers = { 'Content-Type': 'text/javascript; charset=utf-8' }; | |
+ var image = new mapnik.Grid(meta.width, meta.height); | |
+ try { | |
+ source._stats.render++; | |
+ map.render(image, options, function(err, image) { | |
+ process.nextTick(function() { | |
+ // Release after the .render() callback returned | |
+ // to avoid mapnik errors. | |
+ source._pool.release(map); | |
+ }); | |
+ if (err) return callback(err); | |
+ if (meta.tiles.length > 1) { | |
+ sliceMetatile(image, options, meta, callback); | |
+ } else { | |
+ encodeSingleTile(image, options, meta, callback); | |
+ } | |
}); | |
+ } catch(err) { | |
+ source._pool.release(map); | |
+ callback(err); | |
+ } | |
- if (err) return callback(err); | |
- | |
- if (meta.tiles.length > 1) { | |
- sliceMetatile(image, options, meta, callback); | |
- } else { | |
- encodeSingleTile(image, options, meta, callback); | |
+ } else { | |
+ options.headers = { 'Content-Type': 'image/png' }; | |
+ if (options.format.indexOf('jpeg') != -1) { | |
+ options.headers = { 'Content-Type': 'image/jpeg' }; | |
+ } | |
+ images.acquire(meta.width,{},function(err,image) { | |
+ if (err) { | |
+ images.release(meta.width,image); | |
+ return callback(err); | |
+ } | |
+ if (image.reused) { | |
+ image.clear(); | |
+ } | |
+ image.reused = true; | |
+ try { | |
+ source._stats.render++; | |
+ map.render(image, options, function(err, image) { | |
+ process.nextTick(function() { | |
+ // Release after the .render() callback returned | |
+ // to avoid mapnik errors. | |
+ source._pool.release(map); | |
+ }); | |
+ if (err) return callback(err); | |
+ if (meta.tiles.length > 1) { | |
+ sliceMetatile(image, options, meta, function(err,tiles) { | |
+ images.release(meta.width,image); | |
+ callback(err,tiles); | |
+ }); | |
+ } else { | |
+ encodeSingleTile(image, options, meta, function(err,tiles) { | |
+ images.release(meta.width,image); | |
+ callback(err,tiles); | |
+ }); | |
+ } | |
+ }); | |
+ } catch(err) { | |
+ source._pool.release(map); | |
+ images.release(meta.width,image); | |
+ callback(err); | |
} | |
}); | |
- } catch(err) { | |
- source._pool.release(map); | |
- callback(err); | |
} | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment