#javascript #python #plotly
#javascript #python #высокая производительность
Вопрос:
Я пытаюсь создать панель мониторинга в реальном времени, используя Python / Flask и Plotly JS. Я настроил веб-сокет (SocketIO) для перекачки данных в plotly и обновляю данные графика на основе этого. Чего я хотел бы добиться, так это построения графиков в реальном времени с частотой> 5 Гц (можно сортировать точки по пакетам каждые 200 мс).
Проблема в том, что в настоящее время, похоже, полностью отключает мой браузер, когда я делаю это с более чем ~ 5 графиками. Пожалуйста, посмотрите ниже, чего я пытаюсь достичь.
Я настроил его в JS следующим образом: (9x)
<script>
Plotly.plot('X_AXIS',
[{x:[0],
y:[0],
type:'scatter'}],
{
width: document.getElementById("col").offsetWidth,
height:0.33 * document.getElementById("DataContent").offsetHeight,
plot_bgcolor:"white",
paper_bgcolor:("#ecc060"),
margin:{l:15,r:15,t:30,b:30},
xaxis: {range:[0,100]},
yaxis: {range:[-10,10]},
title: {text:'X-Axis'}
}
);
</script>
С функцией обновления данных с помощью updateTraces:
socket.on('UpdateTelemetry',function(Data){
Plotly.extendTraces('X_AXIS',{x:[[Data[0][0]]],y:[[Data[0][1]]]},[0],100);
Plotly.extendTraces('Y_AXIS',{x:[[Data[1][0]]],y:[[Data[1][1]]]},[0],100);
Plotly.extendTraces('Z_AXIS',{x:[[Data[2][0]]],y:[[Data[2][1]]]},[0],100);
Plotly.extendTraces('X_AXIS2',{x:[[Data[0][0]]],y:[[Data[0][1]]]},[0],100);
Plotly.extendTraces('Y_AXIS2',{x:[[Data[1][0]]],y:[[Data[1][1]]]},[0],100);
Plotly.extendTraces('Z_AXIS2',{x:[[Data[2][0]]],y:[[Data[2][1]]]},[0],100);
Plotly.extendTraces('X_AXIS3',{x:[[Data[0][0]]],y:[[Data[0][1]]]},[0],100);
Plotly.extendTraces('Y_AXIS3',{x:[[Data[1][0]]],y:[[Data[1][1]]]},[0],100);
Plotly.extendTraces('Z_AXIS3',{x:[[Data[2][0]]],y:[[Data[2][1]]]},[0],100);
});
Я пытался перейти на scattergl, но, честно говоря, производительность кажется хуже, чем просто scatter. Похоже, что plotly просто забивает все процессорное время, которое браузер получает для JS-кода, что означает, что остальная часть страницы становится почти полностью невосприимчивой. (больше даже не могу открывать выпадающие меню)
Есть ли более эффективный способ сделать это?
Ответ №1:
Я пытаюсь сделать что-то очень похожее и заметил те же ограничения Plotly. Я думаю, причина в том, что когда вы это делаете extendTraces
, вы перерисовываете каждый график последовательно, он не объединяется в один рендеринг (https://github.com/plotly/plotly.js/blob/master/src/plot_api/plot_api.js#L935-L939 ). Однако существует способ вызывать extendTraces
только один раз для всех трасс одновременно, что кажется гораздо более производительным (см. https://plotly.com/javascript/streaming/#streaming-subplots и https://codepen.io/federicomassa/pen/bGqGNeK ). Существенная разница здесь заключается в том, что по сравнению с вашим кодом я вызываю только extendTraces
один раз, что, как я полагаю, приводит к перерисовке за одну итерацию рендеринга.
Если вы уже знали об этом решении и думали, что оно неприменимо к вашему случаю, потому что у вас есть асинхронные данные, поступающие для каждого графика, решение, которое я выбрал, — выбрать частоту обновления (скажем, 25 Гц) и собрать все данные, поступающие между двумя итерациями, в хранилище данных, которое вы можетеболее поздний запрос во время каждой итерации обновления. Вы даже можете хранить данные в простой структуре, подобной объекту Javascript, например:
{
data: {
measure1: [
{
timestamp: ...,
value: ...
}, ...
],
measure2: ...
}
}
Теперь во время каждого обновления вы можете вызывать extendTraces
только один раз со всеми новыми измерениями для каждого подзаголовка.