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

Performance of CyLeaflet for larger numbers of nodes (>1000) #210

Closed
emilykl opened this issue Mar 4, 2024 · 1 comment · Fixed by #217
Closed

Performance of CyLeaflet for larger numbers of nodes (>1000) #210

emilykl opened this issue Mar 4, 2024 · 1 comment · Fixed by #217

Comments

@emilykl
Copy link
Contributor

emilykl commented Mar 4, 2024

Description

The below code instantiates a CyLeaflet instance with 1000 nodes. It takes about 3 seconds to load in my browser (Mac OS 12.6; Chrome 120.0). A plain cyto.Cytoscape instance with the same 1000 nodes loads in <0.5s.

The profiler shows the code is spending a lot of time in this event handler:

        cy.on('dragfree add remove', (_) => {
            this.props.setProps({
                elements: cy.elements('').map((item) => {
                    if (item.json().group === 'nodes') {
                        return {
                            data: item.json().data,
                            position: item.json().position,
                        };
                    }
                    return {
                        data: item.json().data,
                        position: void 0,
                    };
                }),
            });
        });

which is triggered each time a node is added, removed, or dragged.

It makes sense that the event handler would be triggered while nodes are being added to the layout, but not clear why it's taking so much longer when part of cyto.CyLeaflet compared to just cyto.Cytoscape. More investigation needed.

Steps/Code to Reproduce

import dash
from dash import html, dcc, callback, Input, Output
import dash_cytoscape as cyto
import dash_leaflet as dl

lat_init = 45.5
lon_init = -73.576

print("Preparing elements")
elements = [
    {"data": {"id": str(x), "lat": lat_init + x / 1000, "lon": lon_init}}
    for x in range(1000)
]
print("Elements created.")

stylesheet = [
    {
        "selector": "node",
        "style": {
            "width": 1000,
            "height": 100,
            "background-color": "red",
        },
    },
]


def serve_layout():
    return html.Div(
        children=[
            html.H1("DASH CYTOSCAPE - Maximum number of nodes"),
            html.Hr(),
            dcc.Markdown(
                """
            * Displaying up to 1000 elements seems doable, but more than that the browser may crash.
            """
            ),
            cyto.CyLeaflet(
                id="cyleaflet",
                cytoscape_props=dict(
                    elements=elements,
                    stylesheet=stylesheet,
                ),
            ),
        ],
    )


app = dash.Dash(__name__)
server = app.server
app.layout = serve_layout


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

Expected Results

Actual Results

Versions

@Farkites
Copy link
Contributor

The event ('dragfree add remove') gets trigger for each individual node added. So initially it would get triggered 1000 times for this code you have provided. Adding a debounce should fix this without changing any functionality.

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 a pull request may close this issue.

2 participants