Я создаю веб-приложение для имитации обработки некоторых реальных данных. Частично это генерирует смоделированные данные, которые я моделирую очень просто как dr aws из нормального распределения во времени. Я подумал, что было бы неплохо построить эти данные, так как они тикают в режиме реального времени вместе со скользящим средним (результат см. Ниже). Я использую реагировать и заговор , в частности реагировать заговор на достижение sh это.
Я был очень доволен результатом, пока не сложил несколько этих сюжетов на одной странице и не понял, что он начинает сильно пыхтеть. По общему признанию, я не работаю на новейших машинах, но все же, я был удивлен, что только несколько графиков на экране при 10 отрисовках в секунду c вызывали скачок ЦП выше 100%, распространяющийся по ядрам.
Итак, мой вопрос: есть ли более эффективные опции для отображения тиковых данных в браузере? Моя единственная мысль состояла в том, чтобы использовать scattergl
тип графика plotly вместо scatter
, но, похоже, это не имеет значения. С другой стороны, я делаю что-то явно глупое в своем текущем коде, или, возможно, есть какой-то способ, которым я мог бы оптимизировать это, чего не вижу?
Полный код ниже, сводится только к соответствующим частям и комментируется для ясность. Заранее спасибо.
import React, { useState, useEffect } from "react";
import Plot from "react-plotly.js";
import randNormal from "@stdlib/random/base/normal";
import range from "lodash.range";
export default function SimulationSettingRunningAverage({
mean,
std,
decayRate,
drawsPerSecond,
}) {
const historyToKeep = drawsPerSecond * 3;
const [runningAverage, setRunningAverage] = useState([mean]);
const [drawHistory, setDrawHistory] = useState([mean]);
// create a trigger to create a draw timer
useEffect(() => {
const draw = () => {
const sample = randNormal(mean, std);
// set draw history, slicing off the oldest value if at capacity
setDrawHistory((dh) => [
...dh.slice(dh.length > historyToKeep ? 1 : 0),
sample,
]);
// set running average by decaying the next most recent value and slicing
// off the oldest value if at capacity
setRunningAverage((ra) => [
...ra.slice(ra.length > historyToKeep ? 1 : 0),
ra.slice(-1).pop() * (1 - decayRate) + decayRate * sample,
]);
};
const id = setInterval(draw, 1000 / drawsPerSecond);
return () => clearInterval(id);
}, [
mean,
std,
decayRate,
drawsPerSecond,
historyToKeep,
setDrawHistory,
setRunningAverage,
]);
return (
<React.Fragment>
<Plot
data={[
{
x: range(0, drawHistory.length),
y: drawHistory,
name: "Draws",
type: "scattergl",
mode: "markers",
marker: { color: "red" },
},
{
x: range(0, runningAverage.length),
y: runningAverage,
name: "Running average",
type: "scattergl",
mode: "lines",
line: { color: "black" },
},
]}
layout={{
title: "Latest draws",
width: 320,
height: 240,
margin: { l: 50, r: 30, t: 30, b: 30 },
xaxis: {
range: [0, historyToKeep],
showticklabels: false,
zeroline: false,
title: "Time",
},
yaxis: {
range: [mean - std * 4, mean + std * 4],
zeroline: false,
title: "Value",
},
showlegend: true,
legend: {
x: 1,
xanchor: "right",
y: 1,
bgcolor: "rgba(0, 0, 0, 0)",
},
}}
config={{ staticPlot: true }}
/>
</React.Fragment>
);
}