Main Content

避免更新静态数据

如果每次更新屏幕时只有一小部分定义图形场景的数据发生变化,那么您可以通过只更新发生变化的数据从而提高性能。下例演示了这一技术。

性能不佳的代码性能更高的代码

在此示例中,通过每次遍历循环时创建两个对象,让标记沿着曲面移动。

[sx,sy,sz] = peaks(500);
nframes = 490;

for t = 1:nframes
   surf(sx,sy,sz,'EdgeColor','none')
   hold on
   plot3(sx(t+10,t),sy(t,t+10),...
         sz(t+10,t+10)+0.5,'o',...
        'MarkerFaceColor','red',...
        'MarkerSize',14)
   hold off
   drawnow
end

创建曲面,然后在循环中更新标记的 XDataYDataZData。每次迭代时仅改变标记数据。

[sx,sy,sz] = peaks(500);
nframes = 490;

surf(sx,sy,sz,'EdgeColor','none')
hold on
h = plot3(sx(1,1),sy(1,1),sz(1,1),'o',...
   'MarkerFaceColor','red',...
   'MarkerSize',14);
hold off

for t = 1:nframes
   set(h,'XData',sx(t+10,t),...
      'YData',sy(t,t+10),...
      'ZData',sz(t+10,t+10)+0.5)
   drawnow
end

分割数据以减少更新次数

考虑以下情况,当代码在循环中执行时,对象数据变得很大,例如随时间追踪信号的线条。

每次调用 drawnow,更新都被传递到渲染器。随着数据数组不断变大,性能下降很快。如果您使用这个模式,采用右侧示例中描述的分段方法。

性能不佳的代码性能更高的代码
% Grow data
figure('Position',[10,10,1500,400])
n = 5000;


h = stairs(1,1);
ax = gca;
ax.XLim = [1,n];
ax.YLim = [0,1];
ax.ZLim = [0,1];
ax.NextPlot = 'add';

xd = 1:n;
yd = rand(1,n);

tic
for ix = 1:n
   set(h,'XData',xd(1:ix),'YData',yd(1:ix));
   drawnow;
end
toc
% Segment data
figure('Position',[10,10,1500,400])
n = 5000;
seg_size = 500;
xd = 1:n;
yd = rand(1,n);

h = stairs(1,1);
ax = gca;
ax.XLim = [1,n];
ax.YLim = [0,1];
ax.ZLim = [0,1];
ax.NextPlot = 'add';

tic
start = 1;
for ix=1:n
   % Limit object size
   if (ix-start > seg_size)
      start = ix-1;
      h = stairs(1,1);
   end
   set(h,'XData',xd(start:ix),...
      'YData',yd(start:ix));
   % Update display in 50 point chunks
   if mod(ix,50) == 0
      drawnow;
   end
end
toc

这段代码性能更高,因为限制因素是更新时发送的数据量。