Skip to content

Optimize performance of setCategoryIndex #1544

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

Merged
merged 13 commits into from
Apr 10, 2017
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
27 changes: 20 additions & 7 deletions src/plots/cartesian/set_convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,22 +126,33 @@ module.exports = function setConvert(ax, fullLayout) {
*/
function setCategoryIndex(v) {
if(v !== null && v !== undefined) {
var c = ax._categories.indexOf(v);
if(c === -1) {
if(ax._categoriesMap === undefined) {
ax._categoriesMap = {};
}

if(ax._categoriesMap[v] !== undefined) {
return ax._categoriesMap[v];
} else {
ax._categories.push(v);
return ax._categories.length - 1;

var curLength = ax._categories.length - 1;
ax._categoriesMap[v] = curLength;

return curLength;
}
return c;
}
return BADNUM;
}

function getCategoryIndex(v) {
// d2l/d2c variant that that won't add categories but will also
// allow numbers to be mapped to the linearized axis positions
var index = ax._categories.indexOf(v);
if(index !== -1) return index;
if(typeof v === 'number') return v;
if(ax._categoriesMap) {
var index = ax._categoriesMap[v];
if(index !== undefined) return index;
}

if(typeof v === 'number') { return v; }
}

function l2p(v) {
Expand Down Expand Up @@ -325,6 +336,8 @@ module.exports = function setConvert(ax, fullLayout) {

// TODO cleaner way to handle this case
if(!ax._categories) ax._categories = [];
// Add a map to optimize the performance of category collection
if(!ax._categoriesMap) ax._categoriesMap = {};

// make sure we have a domain (pull it in from the axis
// this one is overlaying if necessary)
Expand Down
9 changes: 9 additions & 0 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -1950,6 +1950,13 @@ plots.doCalcdata = function(gd, traces) {
// to be filled in later by ax.d2c
for(i = 0; i < axList.length; i++) {
axList[i]._categories = axList[i]._initialCategories.slice();

// Build the lookup map for initialized categories
axList[i]._categoriesMap = {};
for(j = 0; j < axList[i]._categories.length; j++) {
axList[i]._categoriesMap[axList[i]._categories[j]] = j;
}

if(axList[i].type === 'category') hasCategoryAxis = true;
}

Expand Down Expand Up @@ -1994,6 +2001,8 @@ plots.doCalcdata = function(gd, traces) {
axList[i]._min = [];
axList[i]._max = [];
axList[i]._categories = [];
// Reset the look up map
axList[i]._categoriesMap = {};
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/traces/scatter/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ module.exports = function plot(gd, plotinfo, cdscatter, transitionOpts, makeOnCo
// Sort the traces, once created, so that the ordering is preserved even when traces
// are shown and hidden. This is needed since we're not just wiping everything out
// and recreating on every update.
for(i = 0, uids = []; i < cdscatter.length; i++) {
uids[i] = cdscatter[i][0].trace.uid;
for(i = 0, uids = {}; i < cdscatter.length; i++) {
uids[cdscatter[i][0].trace.uid] = i;
}

scatterlayer.selectAll('g.trace').sort(function(a, b) {
var idx1 = uids.indexOf(a[0].trace.uid);
var idx2 = uids.indexOf(b[0].trace.uid);
var idx1 = uids[a[0].trace.uid];
var idx2 = uids[b[0].trace.uid];
return idx1 > idx2 ? 1 : -1;
});

Expand Down
2 changes: 2 additions & 0 deletions test/jasmine/tests/axes_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1685,6 +1685,7 @@ describe('Test axes', function() {
var ax = {
type: 'category',
_categories: ['a', 'b', 'c', 'd'],
_categoriesMap: {'a': 0, 'b': 1, 'c': 2, 'd': 3},
tickmode: 'array',
tickvals: ['a', 1, 1.5, 'c', 2.7, 3, 'e', 4, 5, -2],
ticktext: ['A!', 'B?', 'B->C'],
Expand Down Expand Up @@ -1804,6 +1805,7 @@ describe('Test axes', function() {

function _autoBin(x, ax, nbins) {
ax._categories = [];
ax._categoriesMap = {};
Axes.setConvert(ax);

var d = ax.makeCalcdata({ x: x }, 'x');
Expand Down