Real time plotting slow: FigureController.flushCoalescer needs a lot of memory and cpu time
Show older comments
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 Comments
Jan Kappen
on 16 Sep 2019
Arturo Pino
on 16 Aug 2020
Edited: Arturo Pino
on 16 Aug 2020
I'm also having a very similar issue, program getting hung up using figurecontroller.flushcoalescer. Has anyone seen this issue or find a resolution? I noticed in the figurecontroller method, the following comment was added by Mathworks:
%Used by figure.flushCoalescer() to implement the short-term solution
%for drawnow property updates. When the long-term solution is
%implemented, this method can be removed; see g1658467.
It then just gets stuck in a loop checking if "this.PeerModeInfo" has been set.
Eleanor Betton
on 18 Aug 2021
I am still getting this in Appdesigner on MatLan 2021a. Any advice?
li li
on 14 Oct 2021
I am still getting this in Appdesigner on matlab 2020b.
li li
on 17 Oct 2021
I tried to change BusyMode = 'drop' and the error no longer appears.
Jan Kappen
on 8 Nov 2021
Answers (0)
Categories
Find more on Startup and Shutdown in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!