Black Lives Matter. Please consider donating to Black Girls Code today.

Dash Core Component performance issues on mapbox graphs between versions

Hi everyone,

We noticed a severe performance issue with Dash-Core-Components.

When loading a mapbox graph with lots of layers and fewer points, the loading and rendering goes from ~5 seconds to ~56 seconds from versions to versions.

Here are the versions I have tested so far:

dash-core-components 0.28.0      -> 5 Seconds but no dcc.Store
dash-core-components 0.30.2      -> !!! 56 Seconds
dash-core-components 0.31.0      -> !!! 56 Seconds
dash-core-components 0.31.0rc1   -> 5 Seconds but issues with tabs layout so I can't use it
dash-core-components 0.32.0      -> !!! 56 Seconds
dash-core-components 0.33.0      -> !!! App fail completely, no rendering
dash-core-components 0.34.0      -> !!! App fail completely, no rendering

I have implemented dcc.Store, that’s why I wanted to upgrade to a newer version.
Notice that 0.31.0rc1 is fast to render, yet 0.31.0 is slow to render.

All those tests were performed on Chrome. Firefox, Safari and other are usually slower to render mapbox graphs already, and I suspect the problem to be similar (I can run tests if needed).

All the other components were put to their maximum upgrade, but I also tried with:

dash==0.28.5
dash-auth==1.2.0
dash-html-components==0.13.2
dash-renderer==0.14.3
dash-table-experiments==0.6.0

for the same results.

Funnily, versions 0.33 and 0.34 just fail completely to render unless on an older version of my app, while the newer version of my works fine with those versions, except slower. it starts to be a nightmare to maintain an app…

Any hint on how I can fix that?

Cheers

Are you using the dcc.Store to store the data for the graph ?

0.30.0 is when the dev bundle support was added, are you running with debug=True and app.scripts.config.serve_locally=True ? If so, can you try without the dev bundles by changing app.run_server(dev_tools_serve_dev_bundles=False) and see if it improves ?

Hi Philippe!

Thanks for the quick reply.

I am indeed running with debug=True but I am not using the app.scripts.config.serve_locally=True as I believe that serving locally would just slow down the overall page rendering.

I have tried with:

app = dash.Dash('auth', sharing=True, server=server,
                static_folder='static', dev_tools_serve_dev_bundles=False)

as you suggest but it did not help on rendering the mapbox any faster nor rendering the layout at all with dash-core-components > 0.32.0

As well, I noticed that dev_tools_serve_dev_bundles came with dash 0.27.0. On my side, I had already upgraded to 0.28.5 and run the different versions of dash-core-components without up or downgrading dash at all.

Any other suggestion?

PS: I notice that I had the versions of the other packages used wrong in my first message, I have edited it to have it correct. My statement that all other packages were updated to their maximum upgrade was correct though. Sorry about that.

Could you create a small, reproducable example that is similar to your app? That way, we can debug what might be going wrong. Looking at our CHANGELOG for this package (https://github.com/plotly/dash-core-components/blob/master/CHANGELOG.md), it’s difficult to know what might have caused the issue.

Hi chriddyp, thanks for the quick reply!

Alright, I manage to reduce the app by a significant amount yet showing the bug:

There are 4 files (at the end of this message).

I use the following version for my test

dash==0.28.5
dash-auth==1.2.0
dash-html-components==0.13.2
dash-renderer==0.14.3
Flask==1.0.2
plotly==3.3.0 (is it called ?)

and in between two tests, I only change

dash-core-components==0.32.0

to

dash-core-components==0.28.0

and vice-versa.

At the launch of the app (python main.py), there should be a graph (mapbox) and a dropdown (just to initialise the map).
The map shows the world plus some layers around Santiago (Chile). I have put 10 layers of 1000 polygons as an example, but you can add more polygons if you want to see the problems enhanced.

You should notice that by changing the dash-core-components version, the rendering time varies from almost instantly for version 0.28.0 to more than 10 seconds for version 0.32.0 on my mac pro (2017).

I ll edit this message if I remember anything important, and let me know if I should add anything!

Thanks a lot!

main.py:

import os
import flask
import dash
import dash_auth
import layout as lay
from server import app, server

app.layout = lay.serve_layout

if __name__ == '__main__':
    server.run(host='127.0.0.1', debug=True)

server.py

import dash
import flask

server = flask.Flask(__name__)
app = dash.Dash(sharing=True, server=server,
                static_folder='static', dev_tools_serve_dev_bundles=False)
app.config['suppress_callback_exceptions']=True

app.index_string = '''
<!DOCTYPE html>
<html>
    <head>
        {%metas%}
        <title>Mosaic</title>
        <link rel="icon" href="/assets/favicon.ico" type="image/x-icon" />
        {%css%}
    </head>
    <body>
        {%app_entry%}
        <footer>
            {%config%}
            {%scripts%}
        </footer>
    </body>
</html>
'''

layout.py

import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output

from server import app
import callbacks

def serve_layout():
    return html.Div([
         dcc.Graph(
                id='map_general',
                config={'displayModeBar': False,},
                style={'height': '450px'},
         ),
         dcc.Dropdown(
                id='features_unified',
                options= [{'label': '1',
                           'value': '1'},
                           {'label': '2',
                            'value': '2'},
                           {'label': '3',
                            'value': '3'}],
                value='1',
         ),])

callbacks.py

import geojson as gj
from dash.dependencies import Input, Output
import random
from server import app

@app.callback(Output('map_general', 'figure'),
              [Input('features_unified', 'value')])
def create_main_map(feature):

    layout_map_tab1= dict(
        autosize=True,
        height=450,
        font=dict(color='#CCCCCC'),
        titlefont=dict(color='#CCCCCC', size='10'),
        margin=dict(l=0, r=0, b=0, t=0),
        hovermode="closest",
        showlegend=False,
        plot_bgcolor="#191A1A",
        paper_bgcolor="#191A1A",
        title='',
        mapbox=dict(
            accesstoken='pk.eyJ1IjoiamFja2x1byIsImEiOiJjajNlcnh' + \
                        '3MzEwMHZtMzNueGw3NWw5ZXF5In0.fk8k06T96' + \
                        'Ml9CLGgKmk81w',
            style="dark",
            center=dict(lon=0, lat=0),
            zoom=1,
        )
    )

    layers = []
    for n in range(1, 10):
        poly = []
        for nn in range(1, 1000):
            minlat = random.uniform(-33.7, -33.5)
            minlon = random.uniform(-70.9, -70.6)
            maxlat = random.uniform(-33.5, -33.3)
            maxlon = random.uniform(-70.6, -70.3)
            poly.append([[minlon, minlat], [maxlon, minlat], [maxlon, maxlat], [minlon, maxlat], [minlon, minlat]])
        poly = '{"geometry": {"coordinates": ['+str(poly)+'], "type": "MultiPolygon"}, "properties": {}, "type": "Feature"}'
        layer = dict(
            sourcetype = 'geojson',
            source = gj.loads(poly),
            below = "water",
            type = 'fill',
            color = '#770000',
            opacity = 0.7,)
        layers.append(layer)

    layout_map_tab1['mapbox']['layers'] = layers

    data = []
    data.append(
        dict(
            type='scattermapbox',
            lat=[0],
            lon=[0],
            text=[0],
            hoverinfo='text',
            showlegend=False,
        )
    )

    return dict(data=data, layout=layout_map_tab1)

Hi @chriddyp

Out of curiosity, have you managed to reproduce the problem? I have made further tests, and found out that the problems also occurs with the newest version of dcc, namely 0.34.0 and 0.35.0 (I couldn’t those versions before finding out that dcc.Store do no longer accepts None, crashing the app without error nor messages).

I also tried on Firefox, Safari, and Chrome, and the problem is the same.

Anything I can do to help, let me know!

Cheers

Hey @Rom1,

did you manage to fix this bug? I am facing the same problem.

Cheers

Unfortunately no… Since it was not utterly critical for us at this stage and we can’t sponsor a fix, we were waiting for an eventual fix. I ll let you know if we find a solution meanwhile.
I noticed that @chriddyp reported the issue on github but I don’t believe that this is a priority to them. You can ask him directly to have news on that side.

@Rom1 @jaotta

I found out this was due to a commit in version 30.2. To get performance back you can build a version and remove clone function around clone(figure.layout) in src\components\Graph.react.js. Then you will need to follow the build instructions. Make sure that dash is pulling in your locally built dash_core_components.min.js in your page source rather than from cdn or wherever else. I added this information to the github issue.

1 Like

Thanks a lot @groch, and good work! Hopefully, this get resolved fast!

I’ve come across this problem now. Have raised a separate post about it but guessing it’s not a popular problem. I have zero knowledge around what @groch suggested… was there a file prepped by someone and instructions for simple people like me to install?

@dweben You need to clone the plotly/dash-core-components repository then remove the clone from figure.layout. Then you need to build. In the repository README there are instructions for building the components (repeated below):

# it's recommended to install your python packages in a virtualenv
# python 2
$ pip install virtualenv --user && virtualenv venv && . venv/bin/activate
# python 3
$ python -m venv && . venv/bin/activate

# make sure dash is installed with dev and testing dependencies
$ pip install dash[dev,testing]  # in some shells you need \ to escape []

# run the build process
$ npm i --ignore-scripts && npm run build

This should generate a dash-core-components.js or perhaps a minified one (it’s been 7 months since I did this). Then, in your page you need to set it up that it loads the right core components rather than from cdn or wherever else it may get them. This could be done through your dash code to your build components. There may be other posts on this, but it shouldn’t be too hard to figure out. Hopefully this helps.

Is there any timeplan to get this issue fixed. The graph get rendered in a second in Plotly & Jupyter but in the dash application it takes almost a minute and is absolutely non responsive. Thank you!