Search code examples
javascriptreactjstypescriptplotlyplotly.js

Slow rendering time | Plotly with Typescript React


I am trying to render a large dataset with plotly. I am plotting a temperature and depth line. When the number of data points is ~100,000 it is unusably slow. However when it has ~85,000 points it works fine.

The reason this is so weird is because having 4 lines with ~85,000 points works really fast still. Even though there is way more data being plotted.

Why is there such a performance discrepancy?

TLDR: Having 4 lines with ~85,000 points is significantly faster than having 2 lines with ~100,000 points.

Here is a sandbox to test it. Try changing increment from 0.07 to 0.06 to see what I mean. Even when only plotting 1 or 2 lines it is still slow.
https://stackblitz.com/edit/react-ts-4fteps?file=index.tsx

import { Col } from 'react-bootstrap';
import Plot from 'react-plotly.js';
import { useState, useEffect } from 'react';

const LinePlot: React.FC = () => {
    const [depthDataPoints, setDepthDataPoints] = useState<number[]>([]);
    const [temperatureDataPoints, setTemperatureDataPoints] = useState<number[]>([]);
    
    const [depthDataPoints2, setDepthDataPoints2] = useState<number[]>([]);
    const [temperatureDataPoints2, setTemperatureDataPoints2] = useState<number[]>([]);

    useEffect(() => {
        // Generate data points for the depth line (0 to 6000 at every 0.01 increment)
        const increment = 0.07;
        const depthPoints = Array.from({ length: Math.ceil(6000 / increment) + 1 }, (_, i) => i * increment);
        setDepthDataPoints(depthPoints);
        setDepthDataPoints2(depthDataPoints.map(y => y * 0.5))

        // Generate data points for the temperature line (fluctuating from 102 F to 165 F)
        const temperaturePoints = depthPoints.map(() => 102 + Math.random() * (165 - 102));
        setTemperatureDataPoints(temperaturePoints);
        setTemperatureDataPoints2(temperatureDataPoints.map(y => y * 2));
    }, []);

    return (
        <Col sm={10}>
            <Plot
                data={[
                    {
                        x: depthDataPoints,
                        y: depthDataPoints,
                        type: 'scattergl',
                        mode: 'lines',
                        name: 'Depth (ft)',
                        line: { color: 'blue' },
                    },
                    {
                        x: depthDataPoints,
                        y: temperatureDataPoints,
                        type: 'scattergl',
                        mode: 'lines',
                        name: 'Temperature (°F)',
                        line: { color: 'red' },
                    },
                    {
                        x: depthDataPoints,
                        y: depthDataPoints2,
                        type: 'scattergl',
                        mode: 'lines',
                        name: 'Depth 2 (ft)',
                        line: { color: 'green' },
                    },
                    {
                        x: depthDataPoints,
                        y: temperatureDataPoints2,
                        type: 'scattergl',
                        mode: 'lines',
                        name: 'Temperature 2 (°F)',
                        line: { color: 'orange' },
                    },
                ]}
                layout={{
                    title: 'Depth and Temperature Plot',
                    xaxis: { title: 'Depth (ft)', range: [0, 6000] },
                    yaxis: { title: 'Measurement', autorange: true },
                    autosize: true,
                }}
                useResizeHandler={true}
                style={{ width: '100%' }}
                config={{ responsive: true }}
            />
        </Col>
    );
};

export default LinePlot;


Solution

  • As strange as it may sound, it works fine when using type: 'scatter' instead of type: 'scattergl', while scattergl is supposed to be faster when having many data points.

    Switching mode from 'lines' to 'markers' produces the same behavior.

    This performance discrepancy is likely due to a bug in the scattergl implementation. You might want to reopen this issue.