Real time plotting slow: FigureCont​roller.flu​shCoalesce​r needs a lot of memory and cpu time

2 views (last 30 days)
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:
Capture.PNG
plotData takes the most time here:
Capture2.PNG
Which seems reasonable, it's a lot of data. But what happens to the FigureController? Look at the memory + cpu time
Capture3.PNG
Could anybody help me out with that? Why is this happening?
Thank you all very much!
  6 Comments

Sign in to comment.

Answers (0)

Categories

Find more on Graphics Performance in Help Center and File Exchange

Products


Release

R2019a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!