Main Content

静的データの更新の回避

画面更新のたびにグラフィックス シーンを定義するデータの小さな部分しか変わらない場合は、変わるデータのみを更新することでパフォーマンスを改善できます。次の例で、この方法を説明します。

パフォーマンスが悪いコードパフォーマンスが良いコード

この例では、マーカーは 1 回ループするたびに両方のオブジェクトを作成して表面に沿って移動します。

[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

このコードのパフォーマンスが高い理由は、パフォーマンスを制限する要因が更新中に送信されるデータ量であるためです。