Dash Renderer very slow at Callback

The React renderer takes ages too add 100k “html.Divs” to the app.layout when using a callback.
Do you guys have an hint, what I could do to improve the performance?

My current code:

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    '''),
    html.Button('Add more', id='button'),
    dcc.Loading(
        html.Div(id='output-data-upload'),
        id="loading",
        type="default",
        )

    ])

### Button Callback
@app.callback(
    Output('output-data-upload', 'children'),
    [Input('button', 'n_clicks')])
def update_output(n_clicks):
    if n_clicks != None:
        divs = []

        for i in range(0,100000):
            divs.append(html.Div(i))

        return divs

if __name__ == '__main__':
    app.run_server(debug=True)

Thanks very much in advance!

@chrisbo

it’s mostly network cost in this case, try clientside callback to avoid the traffic 📣 Dash 0.41.0 released

also post the code in correct format


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

app = dash.Dash(__name__)

app.layout = html.Div(
    children=[
        html.H1(children="Hello Dash"),
        html.Div(
            children="""
        Dash: A web application framework for Python.
    """
        ),
        html.Button("Add more", id="button"),
        dcc.Loading(
            html.Div(id="output-data-upload"), id="loading", type="default"
        ),
    ]
)


@app.callback(
    Output("output-data-upload", "children"), [Input("button", "n_clicks")]
)
def update_output(n_clicks):
    if n_clicks != None:
        return [html.Div(i) for i in range(0, 100000)]


if __name__ == "__main__":
    app.run_server(debug=True)
1 Like

Hi byronz,

thank you very much for the hint with clientside callbacks.
I tried following code, which is much faster.

module1.py :

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

app = dash.Dash(__name__)

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    '''),
    html.Button('Add more', id='button'),
    dcc.Loading(
        html.Div(id='output-data-upload'),
        id="loading",
        type="default",
        )

    ])


app.clientside_callback(
    ClientsideFunction(
        namespace='clientside',
        function_name='add_divs'
    ),
    Output('output-data-upload', 'children'),
    [Input('button', 'n_clicks')]
)

if __name__ == "__main__":
    app.run_server(debug=True)

clientside.js :

if (!window.dash_clientside) { window.dash_clientside = {}; }
window.dash_clientside.clientside = {
    add_divs: function (value) {

        for (i = 0; i < 10000; i++) {
            
            var div = document.createElement("div");
            div.style.background = "red";
            div.style.color = "white";
            div.innerHTML = i;

            document.getElementById("output-data-upload").appendChild(div);
        }
        
    }
}

On loading I get following error:
000011

Seems like the DOM element “output-data-upload” has not rendered yet while loading. What can I do to fix that issue?

@chrisbo

if you look at chris’ examples https://github.com/plotly/dash-renderer/commit/5b9934d17851f467321b80eb9bc198e16b678251. the purpose of the client callback is not to manipulate directly the DOM, but write directly the output. i.e. the add_divs returns a string contains 10000 divs html tags with numbers.

can you please give me a short example how this javascript clientside return string should look like in my case?
In chris’ examples the html Tags are already created in python. he does not create them in the clientside callback.

I tried:

if (!window.dash_clientside) { window.dash_clientside = {}; }
window.dash_clientside.clientside = {
    add_divs: function (n_clicks) {

return "html.Div('Hello World')"
        
    }
}

which did not work out.
Thanks a lot buddy!

try pure html tag <div> number value as your example </div>

unfortunately does not work either :frowning:

does anyone have another hint?

I suspect you should return a dash_html_component Div object instead of directly trying to manipulate the real DOM (which presumably will conflict with the React DOM).

However my JavaScript skills are currently very weak so I wasn’t able to figure out how to import the Div object from Dash after 15 mins of playing around. If I get some more time I’ll do so more reading and try again.

@chrisbo I had some time this morning to play around with your example. So the pure html way won’t work as they are just strings for the parent div.children. The callback way does save a lot of bandwidth if you have a large data set, i.e. you just dump a text from 0 to 10000000000. But if your purpose is to play with the limit of number of components, we might need something else to optimize that. @chriddyp might have more thoughts on this.

What version of dash are you using?

I’ve noticed that since upgrading to 1.0.0, displaying big elements (in my case html tables with ~1000 rows, 75kb of data) is very slow.

When debugging in the browser, it shows that most of the time is spent in “content download”, but when I look in the WSGI logs, the query response time are all much lower than what I see in the browser which is weird. Does the “content download” include the rendering time? In which case maybe that part has got slower.

FYI, there’s a ticket for this issue: https://github.com/plotly/dash/issues/707

Hi @byronz, which is the tool you use in this post to get time executions?

Thanks you.

1 Like

@agarzon that’s from the native chrome dev tools

1 Like

Just updated to

- dash==2.0.0
- dash-bootstrap-components==0.13.0
- dash-core-components==2.0.0
- dash-extensions==0.0.60
- dash-html-components==2.0.0
- dash-table==5.0.0
- dash-tabulator==0.4.2

Now, dash is extremely slow in production and development.

Interesting. Did you measure the difference between the previous version and 2.0?