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

Misc performance optimization #1585

Merged
merged 2 commits into from
May 1, 2017
Merged

Misc performance optimization #1585

merged 2 commits into from
May 1, 2017

Conversation

hy9be
Copy link
Contributor

@hy9be hy9be commented Apr 11, 2017

Following my attempts in #1544, #1555, and #1557, I did some work to further improve the performance of Plotly. I scan through timeline results I captured on slow charts, which has 200+ traces, and did some caching. I also tried to skip processing on some components (e.g. colorbar) when it is enabled for a graph.

By doing all these, I observed about 15% improvements on bar chart and marginal improvements on scatter plot.

@hy9be
Copy link
Contributor Author

hy9be commented Apr 11, 2017

The way I cache those objects is not ideal. Please suggest the desired way to cache objects, during the review. Thanks!

@hy9be
Copy link
Contributor Author

hy9be commented Apr 11, 2017

I skipped the colorbar layout step when colorbar is not enabled for a trace: f4196f9. But the change breaks 4 unit test cases so I decide to roll it back for now. Maybe I misunderstood the necessity of having colorbar layouted during calling marginPushers, even colorbar is not enabled for the plot.

@@ -302,7 +303,7 @@ Plotly.plot = function(gd, data, layout, config) {
.selectAll(query)
.remove();

fullLayout._infolayer.selectAll('g.rangeslider-container')
rangesliderContainers
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. How does this result in a perf improvement?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did not tested separately. Just checked and my tests shows 200ms to 400ms improvement on 200 traces.

When I profile the 200-trace case, the select and selectAll are among top 5 of hot functions. So my thought was caching all the constant selected elements in data loops.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I understand the value of caching selections, but here you're just assigning the selection to a variable: .selectAll is still called inside a loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.selectAll('g.rangeslider-container') is moved out of the loop, maybe that's where the save comes from.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha. Now I see it (it isn't part of the GH diff view). Thanks 👍

@@ -512,32 +513,36 @@ drawing.bBox = function(node) {
return Lib.extendFlat({}, savedBBoxes[saveNum.value]);
}

var test3 = d3.select('#js-plotly-tester'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done. There's only one tester div per page, so might as well cache in the Drawing module object. 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I understand correctly. I did cache the tester div in line 517 and 518 already. Is that what you are referring to?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm saying this is a great commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got used to expect modification suggestions in a code review lol. Thanks!

@@ -205,7 +205,7 @@ Plotly.plot = function(gd, data, layout, config) {
if(trace.visible !== true || !trace._module.colorbar) {
Plots.autoMargin(gd, 'cb' + trace.uid);
}
else trace._module.colorbar(gd, cd);
else if(trace.marker.colorbar) trace._module.colorbar(gd, cd);
Copy link
Contributor

@etpinard etpinard Apr 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new if() makes traces that have root-level colorbar settings (e.g. heatmap, contour, surface) bypass the colorbar draw step.

Something like

else if(Plots.traceIs(trace, 'markerColorscale') && Colorbar.hasColorbar(trace)) {
  trace._module.colorbar(gd, cd);
}

might makes things work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the changes and run test locally. It still fails in the contour/heatmap traces assertion on colorbar, https://github.com/plotly/plotly.js/blob/master/test/jasmine/tests/plot_interact_test.js#L223 and https://github.com/plotly/plotly.js/blob/master/test/jasmine/tests/plot_interact_test.js#L283. Both countColorBars function returns 0.

I will take a look. And it would be great if you could shed some lights here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not find any problems and tried again today, the local test passed this time. Not sure why it failed last time. So I pushed the commit you suggested.

@etpinard
Copy link
Contributor

Thanks (again) @hy9be for these perf improvements 👍

@hy9be
Copy link
Contributor Author

hy9be commented Apr 14, 2017

I fetch and merged the latest master and all tests passed locally, but CI still has couple of cases failed. Not sure why.

@hy9be
Copy link
Contributor Author

hy9be commented Apr 17, 2017

@etpinard I fixed all jasmine test cases but the CI failed at some other commands which I do not know how to debug. Could you please give me some hints here? Basically I do not really understand the error reported by CI...Thanks!

@etpinard
Copy link
Contributor

npm run test-image-gl2d is failing.

I think adding markerColorscale to this list will fix it.

Or perhaps, replacing

else if(Plots.traceIs(trace, 'markerColorscale') || Colorbar.hasColorbar(trace)) {}

with

else if(Plots.traceIs(trace, 'markerColorscale') || Plots.traceIs(trace, 'parcoords') || Colorbar.hasColorbar(trace)) {}

@hy9be
Copy link
Contributor Author

hy9be commented Apr 17, 2017

@etpinard I tried both ways you suggested and did some further investigation, still cannot figure out a way to pass all the image passed.
Considering the amount of improvements we can get from skipping the colorbar layout, and the effort spent and will be spend on this, I am fine with rollbacking this colorbar change and just commit the caching of selections in this PR. Does it sound ok for you guys?

@hy9be
Copy link
Contributor Author

hy9be commented Apr 20, 2017

@etpinard I removed the optimization for colorbar. Now all tests passed. Just let you know.

@etpinard
Copy link
Contributor

etpinard commented Apr 26, 2017

@hy9be looks like this PR is ready to be merged. 🎉

But before, since you chose to not include that colorbar optimisation, can you rebase and remove all the colorbar-related commits locally and then git push -f here?

@etpinard etpinard added this to the 1.27.0 milestone Apr 26, 2017
@hy9be
Copy link
Contributor Author

hy9be commented Apr 29, 2017

@etpinard I removed all colorbar related commits. Please see if that looks good. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants