Repository navigation
Performance issue after v0.40.0 #707
Description
We recently switched to a newer Dash version and noticed our application got considerably slower. While in Dash v0.40.0 it usually took ~20s for a page to load, in the newer versions this goes up to ~55s, or even 90s depending on the browser.
After some digging, it turns out that having a plain HTML table built using dash-html-components considerably slows the page down. We cannot use a dash-table in this case as we need links inside the table.
There is a considerable difference between v0.40.0 and all versions released after, so I'm assuming that whatever is slowing this down was added in v0.40.0. Page load timings for different dash versions and the code examples can be found below.
Any ideas why this became an issue and what can be done to fix this? Thanks!
dash v0.39.0; dash-core-components v0.44.0; dash-html-components v0.14.0; dash-renderer v0.20.0:
- Example 1: ~1s
- Example 2: ~2s
dash v0.40.0; dash-core-components v0.45.0; dash-html-components v0.15.0; dash-renderer v0.21.0:
- Example 1: ~1s
- Example 2: ~2s
dash v0.41.0; dash-core-components v0.46.0; dash-html-components v0.15.0; dash-renderer v0.22.0:
- Example 1: ~1s
- Example 2: ~9-10s
dash v0.42.0; dash-core-components v0.47.0; dash-html-components v0.16.0; dash-renderer v0.23.0:
- Example 1: ~1s
- Example 2: ~9-10s
Example 1:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash()
options = list({'label': 'City %d' % i, 'value': 'city-%d' % i} for i in range(10))
children = []
for i in range(5):
children.extend([
html.Label('Multi-Select Dropdown'),
dcc.Loading(dcc.Dropdown(id='dropdown-%d' % i, options=options, value=['city-0', 'city-1'], multi=True)),
])
app.layout = html.Div(children)
for i in range(4):
@app.callback(
[Output('dropdown-%d' % (i + 1), 'options'), Output('dropdown-%d' % (i + 1), 'value')],
[Input('dropdown-%d' % i, 'value')])
def update_options(value):
return [options, value]
if __name__ == '__main__':
app.run_server(debug=True)
Example 2:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash()
options = list({'label': 'City %d' % i, 'value': 'city-%d' % i} for i in range(10))
children = []
for i in range(5):
children.extend([
html.Label('Multi-Select Dropdown'),
dcc.Loading(dcc.Dropdown(id='dropdown-%d' % i, options=options, value=['city-0', 'city-1'], multi=True)),
])
children += [html.Tr([html.Td('Label'), html.Td(html.A('?action=enable'))])] * 800
app.layout = html.Div(children)
for i in range(4):
@app.callback(
[Output('dropdown-%d' % (i + 1), 'options'), Output('dropdown-%d' % (i + 1), 'value')],
[Input('dropdown-%d' % i, 'value')])
def update_options(value):
return [options, value]
if __name__ == '__main__':
app.run_server(debug=True)
Activity
0x26res commentedon Aug 8, 2019
I'm having the same issue. Updating big html tables has got considerably slower since after 0.40. I had to roll back to 0.40 for now.
byronz commentedon Aug 8, 2019
@popes01a thanks for the elaborated examples for performance issues. there is a major change around 0.40.0 in dash-renderer about the react component hierachy, extra props-check might adds few latency, we will investigate this furthermore.
Few suggestions you can do before that:
children += [html.Tr([html.Td('Label '), html.Td(html.A('?action=enable'))]) for _ in range(800)]will save about 2 seconds from backend.freshwuzhere commentedon Dec 4, 2019
Same issue when I upgraded. My render time went from 0.17 seconds to 3 .1 seconds. Simple tabular data page with 20+ callbacks. Rolled back to 0.40.0 and running fine but major functionality roll back also.
alexcjohnson commentedon Dec 4, 2019
Belated thanks @popes01a for the very clear investigation and report. We will try to dig into this for the next release - which is also expected to reduce the need for these big explicit
html.Tablecomponents by allowing links and images indash-tablebut there will of course always be cases that warrant large explicit layouts of one form or another.popes01a commentedon Dec 5, 2019
I have switched to using a
Dropdownand aContinuebutton to trigger the action for now, but links inside adash-tablecomponent would be ideal. Looking forward to the release!Marc-Andre-Rivet commentedon Jan 10, 2020
Testing out multiple versions of Dash with code modified from example 2 (multi-output was added in 0.39) and to avoid React warnings.
I get the following times for debug=False and dropdown count=5, average of 3 runs.
Looks like 0.35, 0.42, 1.7.0 all have similar performance and 0.40 stands on its own. Will look into running the perf test against more versions and looking more deeply into what's happening during render that would explain the performance differences.
5 remaining items
0x26res commentedon Jun 24, 2020
I've played around with the latest version of dash, and I don't notice the performance issue I was experiencing with 0.41.0+ any more. Maybe this issue has been solved somehow?
alexcjohnson commentedon Jun 24, 2020
@ArthurAndres great! We did improve performance a bunch in #1254 - @Marc-Andre-Rivet when you're back you can extend the table above, and perhaps close this issue?