Real time plotting slow: FigureController.flushCoalescer needs a lot of memory and cpu time
4 views (last 30 days)
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
Answers (0)
See Also
Categories
Find more on Graphics Performance 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!