Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Worker refactor #3404

Merged
merged 2 commits into from
Oct 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 4 additions & 17 deletions bench/benchmarks/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ const Protobuf = require('pbf');
const assert = require('assert');

const WorkerTile = require('../../js/source/worker_tile');
const Worker = require('../../js/source/worker');
const ajax = require('../../js/util/ajax');
const Style = require('../../js/style/style');
const StyleLayerIndex = require('../../js/style/style_layer_index');
const util = require('../../js/util/util');
const Evented = require('../../js/util/evented');
const config = require('../../js/util/config');
Expand Down Expand Up @@ -125,9 +125,9 @@ function preloadAssets(stylesheet, callback) {
}

function runSample(stylesheet, getGlyphs, getIcons, getTile, callback) {
const timeStart = performance.now();
const layerIndex = new StyleLayerIndex(stylesheet.layers);

const layerFamilies = createLayerFamilies(stylesheet.layers);
const timeStart = performance.now();

util.asyncAll(coordinates, (coordinate, eachCallback) => {
const url = `https://a.tiles.mapbox.com/v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/${coordinate.zoom}/${coordinate.row}/${coordinate.column}.vector.pbf?access_token=${config.ACCESS_TOKEN}`;
Expand Down Expand Up @@ -159,7 +159,7 @@ function runSample(stylesheet, getGlyphs, getIcons, getTile, callback) {
getTile(url, (err, response) => {
if (err) throw err;
const data = new VT.VectorTile(new Protobuf(response));
workerTile.parse(data, layerFamilies, actor, (err) => {
workerTile.parse(data, layerIndex.families, actor, (err) => {
if (err) return callback(err);
eachCallback();
});
Expand All @@ -180,16 +180,3 @@ function asyncTimesSeries(times, work, callback) {
callback();
}
}

let createLayerFamiliesCacheKey;
let createLayerFamiliesCacheValue;
function createLayerFamilies(layers) {
if (layers !== createLayerFamiliesCacheKey) {
const worker = new Worker({addEventListener: function() {} });
worker['set layers'](0, layers);

createLayerFamiliesCacheKey = layers;
createLayerFamiliesCacheValue = worker.layerFamilies[0];
}
return createLayerFamiliesCacheValue;
}
6 changes: 3 additions & 3 deletions js/source/geojson_worker_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ module.exports = GeoJSONWorkerSource;
* This class is designed to be easily reused to support custom source types
* for data formats that can be parsed/converted into an in-memory GeoJSON
* representation. To do so, create it with
* `new GeoJSONWorkerSource(actor, styleLayers, customLoadGeoJSONFunction)`. For a full example, see [mapbox-gl-topojson](https://github.com/developmentseed/mapbox-gl-topojson).
* `new GeoJSONWorkerSource(actor, layerIndex, customLoadGeoJSONFunction)`. For a full example, see [mapbox-gl-topojson](https://github.com/developmentseed/mapbox-gl-topojson).
*
* @class GeoJSONWorkerSource
* @private
* @param {Function} [loadGeoJSON] Optional method for custom loading/parsing of GeoJSON based on parameters passed from the main-thread Source. See {@link GeoJSONWorkerSource#loadGeoJSON}.
*/
function GeoJSONWorkerSource (actor, styleLayers, loadGeoJSON) {
function GeoJSONWorkerSource (actor, layerIndex, loadGeoJSON) {
if (loadGeoJSON) { this.loadGeoJSON = loadGeoJSON; }
VectorTileWorkerSource.call(this, actor, styleLayers);
VectorTileWorkerSource.call(this, actor, layerIndex);
}

GeoJSONWorkerSource.prototype = util.inherit(VectorTileWorkerSource, /** @lends GeoJSONWorkerSource.prototype */ {
Expand Down
4 changes: 1 addition & 3 deletions js/source/source.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,7 @@ exports.setType = function (name, type) {
*
* @class WorkerSource
* @param {Actor} actor
* @param {object} styleLayers An accessor provided by the Worker to get the current style layers and layer families.
* @param {Function} styleLayers.getLayers
* @param {Function} styleLayers.getLayerFamilies
* @param {StyleLayerIndex} layerIndex
*/

/**
Expand Down
8 changes: 4 additions & 4 deletions js/source/vector_tile_worker_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ module.exports = VectorTileWorkerSource;
* @private
* @param {Function} [loadVectorData] Optional method for custom loading of a VectorTile object based on parameters passed from the main-thread Source. See {@link VectorTileWorkerSource#loadTile}. The default implementation simply loads the pbf at `params.url`.
*/
function VectorTileWorkerSource (actor, styleLayers, loadVectorData) {
function VectorTileWorkerSource (actor, layerIndex, loadVectorData) {
this.actor = actor;
this.styleLayers = styleLayers;
this.layerIndex = layerIndex;

if (loadVectorData) { this.loadVectorData = loadVectorData; }

Expand Down Expand Up @@ -59,7 +59,7 @@ VectorTileWorkerSource.prototype = {
if (!vectorTile) return callback(null, null);

workerTile.vectorTile = vectorTile;
workerTile.parse(vectorTile, this.styleLayers.getLayerFamilies(), this.actor, (err, result, transferrables) => {
workerTile.parse(vectorTile, this.layerIndex.families, this.actor, (err, result, transferrables) => {
if (err) return callback(err);

// Not transferring rawTileData because the worker needs to retain its copy.
Expand All @@ -85,7 +85,7 @@ VectorTileWorkerSource.prototype = {
uid = params.uid;
if (loaded && loaded[uid]) {
const workerTile = loaded[uid];
workerTile.parse(workerTile.vectorTile, this.styleLayers.getLayerFamilies(), this.actor, callback);
workerTile.parse(workerTile.vectorTile, this.layerIndex.families, this.actor, callback);
}
},

Expand Down
74 changes: 13 additions & 61 deletions js/source/worker.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
'use strict';

const Actor = require('../util/actor');
const StyleLayer = require('../style/style_layer');
const StyleLayerIndex = require('../style/style_layer_index');
const util = require('../util/util');

const VectorTileWorkerSource = require('./vector_tile_worker_source');
const GeoJSONWorkerSource = require('./geojson_worker_source');
const featureFilter = require('feature-filter');
const assert = require('assert');

module.exports = function createWorker(self) {
Expand All @@ -17,8 +16,7 @@ function Worker(self) {
this.self = self;
this.actor = new Actor(self, this);

this.layers = {};
this.layerFamilies = {};
this.layerIndexes = {};

this.workerSourceTypes = {
vector: VectorTileWorkerSource,
Expand All @@ -38,38 +36,11 @@ function Worker(self) {

util.extend(Worker.prototype, {
'set layers': function(mapId, layerDefinitions) {
this.layers[mapId] = {};
this['update layers'](mapId, layerDefinitions);
this.getLayerIndex(mapId).replace(layerDefinitions);
},

'update layers': function(mapId, layerDefinitions) {
const layers = this.layers[mapId];

// Update ref parents
for (const layer of layerDefinitions) {
if (!layer.ref) updateLayer(layer);
}

// Update ref children
for (const layer of layerDefinitions) {
if (layer.ref) updateLayer(layer);
}

function updateLayer(layer) {
if (layer.type !== 'fill' && layer.type !== 'line' && layer.type !== 'circle' && layer.type !== 'symbol')
return;
const refLayer = layer.ref && layers[layer.ref];
let styleLayer = layers[layer.id];
if (styleLayer) {
styleLayer.set(layer, refLayer);
} else {
styleLayer = layers[layer.id] = StyleLayer.create(layer, refLayer);
}
styleLayer.updatePaintTransitions({}, {transition: false});
styleLayer.filter = featureFilter(styleLayer.filter);
}

this.layerFamilies[mapId] = createLayerFamilies(this.layers[mapId]);
this.getLayerIndex(mapId).update(layerDefinitions);
},

'load tile': function(mapId, params, callback) {
Expand Down Expand Up @@ -112,16 +83,18 @@ util.extend(Worker.prototype, {
}
},

getLayerIndex: function(mapId) {
let layerIndexes = this.layerIndexes[mapId];
if (!layerIndexes) {
layerIndexes = this.layerIndexes[mapId] = new StyleLayerIndex();
}
return layerIndexes;
},

getWorkerSource: function(mapId, type) {
if (!this.workerSources[mapId])
this.workerSources[mapId] = {};
if (!this.workerSources[mapId][type]) {
// simple accessor object for passing to WorkerSources
const layers = {
getLayers: () => this.layers[mapId],
getLayerFamilies: () => this.layerFamilies[mapId]
};

// use a wrapped actor so that we can attach a target mapId param
// to any messages invoked by the WorkerSource
const actor = {
Expand All @@ -130,30 +103,9 @@ util.extend(Worker.prototype, {
}
};

this.workerSources[mapId][type] = new this.workerSourceTypes[type](actor, layers);
this.workerSources[mapId][type] = new this.workerSourceTypes[type](actor, this.getLayerIndex(mapId));
}

return this.workerSources[mapId][type];
}
});

function createLayerFamilies(layers) {
const families = {};

for (const layerId in layers) {
const layer = layers[layerId];
const parentLayerId = layer.ref || layer.id;
const parentLayer = layers[parentLayerId];

if (parentLayer.layout && parentLayer.layout.visibility === 'none') continue;

families[parentLayerId] = families[parentLayerId] || [];
if (layerId === parentLayerId) {
families[parentLayerId].unshift(layer);
} else {
families[parentLayerId].push(layer);
}
}

return families;
}
Loading