Real time plotting slow: FigureController.flushCoalescer needs a lot of memory and cpu time
4 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Dear all,
I'm trying to plot data points from a serial device as fast as possible and I think, almost all best practices have been followed. The plot concept is approx like this (it's much more complicated, because it's part of a gui in reality)
classdef SensorPlots < handle
properties
HFig
AxesHandles
LineHandles
Data = nan(300,4) % preallocate 300 samples, 4 different plots
Time = nan(300,4)
ToBePlottedIdx = false(300,4) % indicator, which data needs to be plotted
LastPlottedIdx = repmat({nan},4,1) % idx to avoid dynamic growth of XData/YData
end
methods
function obj = SensorPlots
% load pre configured figure
file = "pathToFig/fig.fig";
obj.HFig = openfig(file);
hh = findobj(obj.HFig,'type','axes');
obj.AxesHandles = hh; % in reality, there are multiple axes
obj.LineHandles = plot(obj.AxesHandles, obj.Time, obj.Data, '.');
% first performance tweaks
hh = obj.AxesHandles;
disableDefaultInteractivity(hh);
hh.Toolbar.Visible = 'off';
hh.Toolbar = [];
hh.Interactions = [];
hh.XAxis.LimitsMode = 'manual';
% timer to periodically update plots
obj.plotTimer = timer('ExecutionMode', 'fixedRate', 'Period', 0.05, 'StartDelay', 0.5, 'TimerFcn', @obj.plotData, 'ErrorFcn', @obj.errorTimer, 'StopFcn', @obj.stopPlotTimer);
end
%% Cache the data in properties Data and Time
% Is called by a Model in MVP context, based on an C# event class.
% gets called every ~40 ms
% dataPack is a struct with fields accX, accY, accZ, temp
function addData(obj, dataPack)
fn = fieldnames(dataPack);
for k = 1:length(fn)
len = length(dataPack.(fn{k}).value);
freeIdx = find(~obj.ToBePlotted(:,k),len,'first');
if isempty(freeIdx)
% disp('plot too slow')
end
obj.Data(freeIdx,k) = cat(1, dataPack.(fn{k}).value);
obj.Time(freeIdx,k) = cat(1, dataPack.(fn{k}).lastUpdate);
obj.ToBePlotted(freeIdx,k) = true;
end
end
%% PlotData callback.
function plotData(obj, sender, evnt)
for iDat = 1:size(obj.Data,2) % 4 cols -> 4 lines plots
plotIdx = find(obj.ToBePlotted(:,iAng));
if isempty(plotIdx)
continue;
end
len = nnz(plotIdx);
try
currLastPlottedIdx = obj.LastPlottedIdx{iDat};
% currLastPlottedIdx not initialized yet?
if any(isnan(currLastPlottedIdx))
currLastPlottedIdx = 1:len;
else
currLastPlottedIdx = currLastPlottedIdx(end) + 1:len;
end
% restrict indices not to be greater than preallocated XData
if(currLastPlottedIdx > size(obj.Data,1))
currLastPlottedIdx = currLastPlottedIdx - min(currLastPlottedIdx) + 1;
end
% plot data
obj.LineHandles(iData).XData(currLastPlottedIdx) = obj.Time(plotIdx,iDat)';
obj.LineHandles(iData).YData(currLastPlottedIdx) = obj.Data(plotIdx,iDat)';
maxTime = max(obj.Time(plotIdx,iDat)');
obj.LastPlottedIdx{iDat} = currLastPlottedIdx;
catch e
e
end
obj.ToBePlotted(plotIdx,iAng) = false;
meanAng(iAng) = mean(obj.Data(plotIdx,iAng));
end
% try not to update the axes limits all the time, but each 500 ms
currentToc = toc(obj.StartTic);
if (currentToc - obj.LastLimitSetTime) > 0.5
for hh = each(obj.AxesHandles)
hh.XAxis.Limits = [maxTime-10,maxTime+5];
end
drawnow limitrate
obj.LastLimitSetTime = currentToc;
end
end
end
end
Do you see any obvious problems with that code? I tried to avoid high level functions an preallocate everything.
The profiler shows that output:
plotData takes the most time here:
Which seems reasonable, it's a lot of data. But what happens to the FigureController? Look at the memory + cpu time
Could anybody help me out with that? Why is this happening?
Thank you all very much!
6 comentarios
Respuestas (0)
Ver también
Categorías
Más información sobre Graphics Performance en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!