MATLAB Answers

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

15 views (last 30 days)
Jan Kappen
Jan Kappen on 18 Jun 2019
Commented: li li on 17 Oct 2021 at 8:40
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!
  5 Comments

Sign in to comment.

Answers (0)

Products


Release

R2019a

Community Treasure Hunt

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

Start Hunting!

Translated by