Updating plot in GNU octave consumes memory












1














I create animations for physics classroom demos by simply updating the plot data using a loop. The problem is that the more complicated animations with many handles and/or vertices consumes a lot of memory. I have tried to both delete 'handle' and set ('handle', xdata...) and I see the same issue.



This working example was my best attempt so that I make sure when I 'set' with new xdata, that the size of the new coordinate arrays are exactly the same size as the arrays being replaced, avoiding (so I thought) the need to go search for some new memory real estate that can accommodate the new array. This small example grows to about 5x memory usage for the octave thread from start to finish even though I am just re-'set'ing a single point. How can I do this so that every time I change the handle's data I don't eat more memory? I am using Octave 4.4 Thanks!



clear all;
close all;
figure('position',[50,50,800,600]);

planetx=ones(15000,1);

planety=ones(15000,1);

planetz=ones(15000,1);

N=size(planetx)(1,1)
h=scatter3(planetx(1,:),planety(1,:),planetz(1,:) , 'filled');
hold on;
p1=plot3([planetx(1,1),zeros(1,70)],[planety(1,1),zeros(1,70)], [planety(1,1),zeros(1,70)],'color','k','markersize',3,'*');

title(sprintf('YEAR=%f',2000+i/N*200 ))
axis([-15,15,-15,15,-15,15],'square');
set(gca,'fontsize',20)
axis('manual')
set(gca, 'cameraviewanglemode', 'manual')
view([15,15]);

n1=69;
i=1;

play='y' #input("'y' to replay, any button to close!","s")
while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if (i<(n1+1))
zer=zeros(1, 70-size(1:i)(1,2));
set(p1, 'xdata',[planetx(1:i,1)',zer],'ydata',[planety(1:i,1)',zer],'zdata',[planetz(1:i,1)',zer])
else
zer=zeros(1, 70-size(i-n1:i)(1,2));
set(p1, 'xdata', [planetx(i-n1:i,1)',zer],'ydata',[planety(i-n1:i,1)',zer],'zdata',[planetz(i-n1:i,1)',zer])
endif;
pause(.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


EDIT: So if instead I use the code



if (i<(n1+1))

set(p1, 'xdata',[planetx(1:i,1)',zeros(1, 70-size(1:i)(1,2))],'ydata',[planety(1:i,1)',zeros(1, 70-size(1:i)(1,2))],'zdata',[planetz(1:i,1)',zeros(1, 70-size(1:i)(1,2))])
else
set(p1, 'xdata', [planetx(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))],'ydata',[planety(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))],'zdata',[planetz(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))])
endif;


...I would think there should be no temporary variables being stored except the handle p1 which is never changing it's dimensions. BUT I still see gradual and just as severe memory creep...










share|improve this question
























  • Interesting. Can I ask what you use to monitor memory usage? So that any experiments I make will be compatible to what you're seeing?
    – Tasos Papastylianou
    Nov 19 at 17:59










  • Indeed, the way you measure memory is relevant here. There is a difference between the memory assigned to a process by the OS, and the memory in use by the process.
    – Cris Luengo
    Nov 20 at 1:24










  • I just keep 'top' open in a terminal and record the 'reserved' memory for octave which starts out about 100MB at the first frame and rises to 500MB at the end. The simulation I cut this out of, with more numerous arrays, starts out at 170MB and climbs to 3GB when it's only half finished. I shouldn't need that much data when a single frame can be rendered with under 200MB.
    – Robert F
    Nov 20 at 3:59










  • MATLAB does the same thing with reserved memory. The reserved memory is irrelevant for most purposes. You need to look at the commited memory (resident set size, RSS, in Linux).
    – Cris Luengo
    Nov 20 at 20:17










  • Also, use @+name to notify someone of a reply. For example, add @Cris to your comment here if you want me pinged about it. (Works only to pinge people that have commented to the same post.)
    – Cris Luengo
    Nov 20 at 20:19
















1














I create animations for physics classroom demos by simply updating the plot data using a loop. The problem is that the more complicated animations with many handles and/or vertices consumes a lot of memory. I have tried to both delete 'handle' and set ('handle', xdata...) and I see the same issue.



This working example was my best attempt so that I make sure when I 'set' with new xdata, that the size of the new coordinate arrays are exactly the same size as the arrays being replaced, avoiding (so I thought) the need to go search for some new memory real estate that can accommodate the new array. This small example grows to about 5x memory usage for the octave thread from start to finish even though I am just re-'set'ing a single point. How can I do this so that every time I change the handle's data I don't eat more memory? I am using Octave 4.4 Thanks!



clear all;
close all;
figure('position',[50,50,800,600]);

planetx=ones(15000,1);

planety=ones(15000,1);

planetz=ones(15000,1);

N=size(planetx)(1,1)
h=scatter3(planetx(1,:),planety(1,:),planetz(1,:) , 'filled');
hold on;
p1=plot3([planetx(1,1),zeros(1,70)],[planety(1,1),zeros(1,70)], [planety(1,1),zeros(1,70)],'color','k','markersize',3,'*');

title(sprintf('YEAR=%f',2000+i/N*200 ))
axis([-15,15,-15,15,-15,15],'square');
set(gca,'fontsize',20)
axis('manual')
set(gca, 'cameraviewanglemode', 'manual')
view([15,15]);

n1=69;
i=1;

play='y' #input("'y' to replay, any button to close!","s")
while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if (i<(n1+1))
zer=zeros(1, 70-size(1:i)(1,2));
set(p1, 'xdata',[planetx(1:i,1)',zer],'ydata',[planety(1:i,1)',zer],'zdata',[planetz(1:i,1)',zer])
else
zer=zeros(1, 70-size(i-n1:i)(1,2));
set(p1, 'xdata', [planetx(i-n1:i,1)',zer],'ydata',[planety(i-n1:i,1)',zer],'zdata',[planetz(i-n1:i,1)',zer])
endif;
pause(.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


EDIT: So if instead I use the code



if (i<(n1+1))

set(p1, 'xdata',[planetx(1:i,1)',zeros(1, 70-size(1:i)(1,2))],'ydata',[planety(1:i,1)',zeros(1, 70-size(1:i)(1,2))],'zdata',[planetz(1:i,1)',zeros(1, 70-size(1:i)(1,2))])
else
set(p1, 'xdata', [planetx(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))],'ydata',[planety(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))],'zdata',[planetz(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))])
endif;


...I would think there should be no temporary variables being stored except the handle p1 which is never changing it's dimensions. BUT I still see gradual and just as severe memory creep...










share|improve this question
























  • Interesting. Can I ask what you use to monitor memory usage? So that any experiments I make will be compatible to what you're seeing?
    – Tasos Papastylianou
    Nov 19 at 17:59










  • Indeed, the way you measure memory is relevant here. There is a difference between the memory assigned to a process by the OS, and the memory in use by the process.
    – Cris Luengo
    Nov 20 at 1:24










  • I just keep 'top' open in a terminal and record the 'reserved' memory for octave which starts out about 100MB at the first frame and rises to 500MB at the end. The simulation I cut this out of, with more numerous arrays, starts out at 170MB and climbs to 3GB when it's only half finished. I shouldn't need that much data when a single frame can be rendered with under 200MB.
    – Robert F
    Nov 20 at 3:59










  • MATLAB does the same thing with reserved memory. The reserved memory is irrelevant for most purposes. You need to look at the commited memory (resident set size, RSS, in Linux).
    – Cris Luengo
    Nov 20 at 20:17










  • Also, use @+name to notify someone of a reply. For example, add @Cris to your comment here if you want me pinged about it. (Works only to pinge people that have commented to the same post.)
    – Cris Luengo
    Nov 20 at 20:19














1












1








1







I create animations for physics classroom demos by simply updating the plot data using a loop. The problem is that the more complicated animations with many handles and/or vertices consumes a lot of memory. I have tried to both delete 'handle' and set ('handle', xdata...) and I see the same issue.



This working example was my best attempt so that I make sure when I 'set' with new xdata, that the size of the new coordinate arrays are exactly the same size as the arrays being replaced, avoiding (so I thought) the need to go search for some new memory real estate that can accommodate the new array. This small example grows to about 5x memory usage for the octave thread from start to finish even though I am just re-'set'ing a single point. How can I do this so that every time I change the handle's data I don't eat more memory? I am using Octave 4.4 Thanks!



clear all;
close all;
figure('position',[50,50,800,600]);

planetx=ones(15000,1);

planety=ones(15000,1);

planetz=ones(15000,1);

N=size(planetx)(1,1)
h=scatter3(planetx(1,:),planety(1,:),planetz(1,:) , 'filled');
hold on;
p1=plot3([planetx(1,1),zeros(1,70)],[planety(1,1),zeros(1,70)], [planety(1,1),zeros(1,70)],'color','k','markersize',3,'*');

title(sprintf('YEAR=%f',2000+i/N*200 ))
axis([-15,15,-15,15,-15,15],'square');
set(gca,'fontsize',20)
axis('manual')
set(gca, 'cameraviewanglemode', 'manual')
view([15,15]);

n1=69;
i=1;

play='y' #input("'y' to replay, any button to close!","s")
while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if (i<(n1+1))
zer=zeros(1, 70-size(1:i)(1,2));
set(p1, 'xdata',[planetx(1:i,1)',zer],'ydata',[planety(1:i,1)',zer],'zdata',[planetz(1:i,1)',zer])
else
zer=zeros(1, 70-size(i-n1:i)(1,2));
set(p1, 'xdata', [planetx(i-n1:i,1)',zer],'ydata',[planety(i-n1:i,1)',zer],'zdata',[planetz(i-n1:i,1)',zer])
endif;
pause(.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


EDIT: So if instead I use the code



if (i<(n1+1))

set(p1, 'xdata',[planetx(1:i,1)',zeros(1, 70-size(1:i)(1,2))],'ydata',[planety(1:i,1)',zeros(1, 70-size(1:i)(1,2))],'zdata',[planetz(1:i,1)',zeros(1, 70-size(1:i)(1,2))])
else
set(p1, 'xdata', [planetx(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))],'ydata',[planety(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))],'zdata',[planetz(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))])
endif;


...I would think there should be no temporary variables being stored except the handle p1 which is never changing it's dimensions. BUT I still see gradual and just as severe memory creep...










share|improve this question















I create animations for physics classroom demos by simply updating the plot data using a loop. The problem is that the more complicated animations with many handles and/or vertices consumes a lot of memory. I have tried to both delete 'handle' and set ('handle', xdata...) and I see the same issue.



This working example was my best attempt so that I make sure when I 'set' with new xdata, that the size of the new coordinate arrays are exactly the same size as the arrays being replaced, avoiding (so I thought) the need to go search for some new memory real estate that can accommodate the new array. This small example grows to about 5x memory usage for the octave thread from start to finish even though I am just re-'set'ing a single point. How can I do this so that every time I change the handle's data I don't eat more memory? I am using Octave 4.4 Thanks!



clear all;
close all;
figure('position',[50,50,800,600]);

planetx=ones(15000,1);

planety=ones(15000,1);

planetz=ones(15000,1);

N=size(planetx)(1,1)
h=scatter3(planetx(1,:),planety(1,:),planetz(1,:) , 'filled');
hold on;
p1=plot3([planetx(1,1),zeros(1,70)],[planety(1,1),zeros(1,70)], [planety(1,1),zeros(1,70)],'color','k','markersize',3,'*');

title(sprintf('YEAR=%f',2000+i/N*200 ))
axis([-15,15,-15,15,-15,15],'square');
set(gca,'fontsize',20)
axis('manual')
set(gca, 'cameraviewanglemode', 'manual')
view([15,15]);

n1=69;
i=1;

play='y' #input("'y' to replay, any button to close!","s")
while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if (i<(n1+1))
zer=zeros(1, 70-size(1:i)(1,2));
set(p1, 'xdata',[planetx(1:i,1)',zer],'ydata',[planety(1:i,1)',zer],'zdata',[planetz(1:i,1)',zer])
else
zer=zeros(1, 70-size(i-n1:i)(1,2));
set(p1, 'xdata', [planetx(i-n1:i,1)',zer],'ydata',[planety(i-n1:i,1)',zer],'zdata',[planetz(i-n1:i,1)',zer])
endif;
pause(.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


EDIT: So if instead I use the code



if (i<(n1+1))

set(p1, 'xdata',[planetx(1:i,1)',zeros(1, 70-size(1:i)(1,2))],'ydata',[planety(1:i,1)',zeros(1, 70-size(1:i)(1,2))],'zdata',[planetz(1:i,1)',zeros(1, 70-size(1:i)(1,2))])
else
set(p1, 'xdata', [planetx(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))],'ydata',[planety(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))],'zdata',[planetz(i-n1:i,1)',zeros(1, 70-size(i-n1:i)(1,2))])
endif;


...I would think there should be no temporary variables being stored except the handle p1 which is never changing it's dimensions. BUT I still see gradual and just as severe memory creep...







memory-leaks octave






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 at 5:08

























asked Nov 17 at 21:07









Robert F

115




115












  • Interesting. Can I ask what you use to monitor memory usage? So that any experiments I make will be compatible to what you're seeing?
    – Tasos Papastylianou
    Nov 19 at 17:59










  • Indeed, the way you measure memory is relevant here. There is a difference between the memory assigned to a process by the OS, and the memory in use by the process.
    – Cris Luengo
    Nov 20 at 1:24










  • I just keep 'top' open in a terminal and record the 'reserved' memory for octave which starts out about 100MB at the first frame and rises to 500MB at the end. The simulation I cut this out of, with more numerous arrays, starts out at 170MB and climbs to 3GB when it's only half finished. I shouldn't need that much data when a single frame can be rendered with under 200MB.
    – Robert F
    Nov 20 at 3:59










  • MATLAB does the same thing with reserved memory. The reserved memory is irrelevant for most purposes. You need to look at the commited memory (resident set size, RSS, in Linux).
    – Cris Luengo
    Nov 20 at 20:17










  • Also, use @+name to notify someone of a reply. For example, add @Cris to your comment here if you want me pinged about it. (Works only to pinge people that have commented to the same post.)
    – Cris Luengo
    Nov 20 at 20:19


















  • Interesting. Can I ask what you use to monitor memory usage? So that any experiments I make will be compatible to what you're seeing?
    – Tasos Papastylianou
    Nov 19 at 17:59










  • Indeed, the way you measure memory is relevant here. There is a difference between the memory assigned to a process by the OS, and the memory in use by the process.
    – Cris Luengo
    Nov 20 at 1:24










  • I just keep 'top' open in a terminal and record the 'reserved' memory for octave which starts out about 100MB at the first frame and rises to 500MB at the end. The simulation I cut this out of, with more numerous arrays, starts out at 170MB and climbs to 3GB when it's only half finished. I shouldn't need that much data when a single frame can be rendered with under 200MB.
    – Robert F
    Nov 20 at 3:59










  • MATLAB does the same thing with reserved memory. The reserved memory is irrelevant for most purposes. You need to look at the commited memory (resident set size, RSS, in Linux).
    – Cris Luengo
    Nov 20 at 20:17










  • Also, use @+name to notify someone of a reply. For example, add @Cris to your comment here if you want me pinged about it. (Works only to pinge people that have commented to the same post.)
    – Cris Luengo
    Nov 20 at 20:19
















Interesting. Can I ask what you use to monitor memory usage? So that any experiments I make will be compatible to what you're seeing?
– Tasos Papastylianou
Nov 19 at 17:59




Interesting. Can I ask what you use to monitor memory usage? So that any experiments I make will be compatible to what you're seeing?
– Tasos Papastylianou
Nov 19 at 17:59












Indeed, the way you measure memory is relevant here. There is a difference between the memory assigned to a process by the OS, and the memory in use by the process.
– Cris Luengo
Nov 20 at 1:24




Indeed, the way you measure memory is relevant here. There is a difference between the memory assigned to a process by the OS, and the memory in use by the process.
– Cris Luengo
Nov 20 at 1:24












I just keep 'top' open in a terminal and record the 'reserved' memory for octave which starts out about 100MB at the first frame and rises to 500MB at the end. The simulation I cut this out of, with more numerous arrays, starts out at 170MB and climbs to 3GB when it's only half finished. I shouldn't need that much data when a single frame can be rendered with under 200MB.
– Robert F
Nov 20 at 3:59




I just keep 'top' open in a terminal and record the 'reserved' memory for octave which starts out about 100MB at the first frame and rises to 500MB at the end. The simulation I cut this out of, with more numerous arrays, starts out at 170MB and climbs to 3GB when it's only half finished. I shouldn't need that much data when a single frame can be rendered with under 200MB.
– Robert F
Nov 20 at 3:59












MATLAB does the same thing with reserved memory. The reserved memory is irrelevant for most purposes. You need to look at the commited memory (resident set size, RSS, in Linux).
– Cris Luengo
Nov 20 at 20:17




MATLAB does the same thing with reserved memory. The reserved memory is irrelevant for most purposes. You need to look at the commited memory (resident set size, RSS, in Linux).
– Cris Luengo
Nov 20 at 20:17












Also, use @+name to notify someone of a reply. For example, add @Cris to your comment here if you want me pinged about it. (Works only to pinge people that have commented to the same post.)
– Cris Luengo
Nov 20 at 20:19




Also, use @+name to notify someone of a reply. For example, add @Cris to your comment here if you want me pinged about it. (Works only to pinge people that have commented to the same post.)
– Cris Luengo
Nov 20 at 20:19












1 Answer
1






active

oldest

votes


















0














I'm assuming you meant to provide a slightly more interesting animation example ... but in any case running this on my octave does not display any noticeable increase in memory usage. Perhaps, as you say, because it's a trivial animation.



However, in general, there's not much you can do for memory optimisation in octave, with the exception of avoiding to create / assign new variables if you can afford to change things in-place, since this avoids the need for allocating new memory to hold the new object. This is also the principle behind assigning index-by-index to a preallocated array in for loops, as opposed to appending an element to the end of an array at each iteration (when you 'append' to an array, you effectively need to allocate space for the now 'larger' array first).



For example, in your example above, instead of calling zeros each time (which allocates a new array in memory) and assigning this new object to 'zer', it may be more efficient to assign the result in-place to each element in the existing 'zer' itself (i.e. zer(:) = zeros(bla bla)). I cannot guarantee this is faster because it depends on how quickly octave destroys the temporary 'zeros' output compared to the unused memory that used to be held by 'zer' before its reallocation ... but it may be something that could make a difference.



The other thing you could try is rely on the fact that octave (like matlab) relies on lazy evaluation. E.g. doing A = B will not allocate new memory for A, until B changes in the meantime; at which point octave 'unlinks' A from B, and allocates space for it at that point to hold the now different array. so if at any point in your animations you find yourself initialising a lot of structures in the same way, you could initialise these with each other, and octave will not allocate extra memory for each component until it needs to. Have a look here if you're interested: https://octave.org/doc/interpreter/Miscellaneous-Techniques.html#Miscellaneous-Techniques



But, honestly though, all this is microoptimisations. Unless you're dealing with huge matrices, I doubt any of this makes a significant difference in terms of memory usage ...



EDIT



Here is some code I tried implementing the above principles (or so I hoped).





% slightly more interesting animation
planetx = 10 * cos(0.1:0.1:1500).';
planety = 10 * sin(0.1:0.1:1500).';
planetz = (planetx + planety);

% ... intermediate code as in question
% [...]

% updated while loop using above concepts
xdata = zeros(70,1); % we will be updating these in place using slices from planetx
ydata = zeros(70,1); % similarly for y and z
zdata = zeros(70,1);

while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if i < (n1 + 1)
xdata(1:i, 1) = planetx(1:i, 1);
ydata(1:i, 1) = planety(1:i, 1);
zdata(1:i, 1) = planetz(1:i, 1);
set(p1, 'xdata', xdata, 'ydata', ydata, 'zdata', zdata)
else
xdata(1 : n1+1, 1) = planetx(i-n1:i, 1);
ydata(1 : n1+1, 1) = planety(i-n1:i, 1);
zdata(1 : n1+1, 1) = planetz(i-n1:i, 1);
set(p1, 'xdatasource', 'xdata', 'ydatasource', 'ydata', 'zdatasource', 'zdata')
endif;
refreshdata;
pause(0.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


This replaced unnecessary calls resulting in temporary allocations (e.g. zeros and size calls), uses updating of preallocated arrays (e.g. xdata) instead of overwriting, and uses xdatasource, which I was hoping would be implemented as a pointer rather than as a reassignment under the hood.



Turns out it's worse memory-wise, if anything. So yeah, worth letting the octave team know. :p






share|improve this answer























  • Funny, I used the 'zer' array so that I would avoid changing the size of the 'xdata'..... for each handle but now I see I have created another source of recreating variables. I will try to work around that now because otherwise I am at the mercy of 'set'. Do you think it's possible that 'set(h,'xdata'...) really doesn't replace but just creates a new variable of the same size?
    – Robert F
    Nov 20 at 3:49










  • I tried fixing the 'zer' array problem in the edit above, but it didn't seem to fix anything.
    – Robert F
    Nov 20 at 4:57










  • well, in a sense you're allocating even more memory now: you have 6 independent 'zeros' instructions. Obviously much of this (including the behaviour of 'set') depends on any optimisations that exist und we the hood, but the idea is to assign by index to a reallocated array, avoiding new allocations. But that still seems overkill. Perhaps you'd get better info from the octave mailing list, which is frequented by the maintainers (SO is not so much).
    – Tasos Papastylianou
    Nov 20 at 9:37










  • @RobertF might be worth opening a bug. I had hopes for using 'xdatasource' instead of 'xdata', but it doesn't seem to work either.
    – Tasos Papastylianou
    Nov 20 at 14:34






  • 1




    Bug report submitted savannah.gnu.org/bugs/index.php?55064
    – Robert F
    Nov 20 at 15:57











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53355594%2fupdating-plot-in-gnu-octave-consumes-memory%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














I'm assuming you meant to provide a slightly more interesting animation example ... but in any case running this on my octave does not display any noticeable increase in memory usage. Perhaps, as you say, because it's a trivial animation.



However, in general, there's not much you can do for memory optimisation in octave, with the exception of avoiding to create / assign new variables if you can afford to change things in-place, since this avoids the need for allocating new memory to hold the new object. This is also the principle behind assigning index-by-index to a preallocated array in for loops, as opposed to appending an element to the end of an array at each iteration (when you 'append' to an array, you effectively need to allocate space for the now 'larger' array first).



For example, in your example above, instead of calling zeros each time (which allocates a new array in memory) and assigning this new object to 'zer', it may be more efficient to assign the result in-place to each element in the existing 'zer' itself (i.e. zer(:) = zeros(bla bla)). I cannot guarantee this is faster because it depends on how quickly octave destroys the temporary 'zeros' output compared to the unused memory that used to be held by 'zer' before its reallocation ... but it may be something that could make a difference.



The other thing you could try is rely on the fact that octave (like matlab) relies on lazy evaluation. E.g. doing A = B will not allocate new memory for A, until B changes in the meantime; at which point octave 'unlinks' A from B, and allocates space for it at that point to hold the now different array. so if at any point in your animations you find yourself initialising a lot of structures in the same way, you could initialise these with each other, and octave will not allocate extra memory for each component until it needs to. Have a look here if you're interested: https://octave.org/doc/interpreter/Miscellaneous-Techniques.html#Miscellaneous-Techniques



But, honestly though, all this is microoptimisations. Unless you're dealing with huge matrices, I doubt any of this makes a significant difference in terms of memory usage ...



EDIT



Here is some code I tried implementing the above principles (or so I hoped).





% slightly more interesting animation
planetx = 10 * cos(0.1:0.1:1500).';
planety = 10 * sin(0.1:0.1:1500).';
planetz = (planetx + planety);

% ... intermediate code as in question
% [...]

% updated while loop using above concepts
xdata = zeros(70,1); % we will be updating these in place using slices from planetx
ydata = zeros(70,1); % similarly for y and z
zdata = zeros(70,1);

while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if i < (n1 + 1)
xdata(1:i, 1) = planetx(1:i, 1);
ydata(1:i, 1) = planety(1:i, 1);
zdata(1:i, 1) = planetz(1:i, 1);
set(p1, 'xdata', xdata, 'ydata', ydata, 'zdata', zdata)
else
xdata(1 : n1+1, 1) = planetx(i-n1:i, 1);
ydata(1 : n1+1, 1) = planety(i-n1:i, 1);
zdata(1 : n1+1, 1) = planetz(i-n1:i, 1);
set(p1, 'xdatasource', 'xdata', 'ydatasource', 'ydata', 'zdatasource', 'zdata')
endif;
refreshdata;
pause(0.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


This replaced unnecessary calls resulting in temporary allocations (e.g. zeros and size calls), uses updating of preallocated arrays (e.g. xdata) instead of overwriting, and uses xdatasource, which I was hoping would be implemented as a pointer rather than as a reassignment under the hood.



Turns out it's worse memory-wise, if anything. So yeah, worth letting the octave team know. :p






share|improve this answer























  • Funny, I used the 'zer' array so that I would avoid changing the size of the 'xdata'..... for each handle but now I see I have created another source of recreating variables. I will try to work around that now because otherwise I am at the mercy of 'set'. Do you think it's possible that 'set(h,'xdata'...) really doesn't replace but just creates a new variable of the same size?
    – Robert F
    Nov 20 at 3:49










  • I tried fixing the 'zer' array problem in the edit above, but it didn't seem to fix anything.
    – Robert F
    Nov 20 at 4:57










  • well, in a sense you're allocating even more memory now: you have 6 independent 'zeros' instructions. Obviously much of this (including the behaviour of 'set') depends on any optimisations that exist und we the hood, but the idea is to assign by index to a reallocated array, avoiding new allocations. But that still seems overkill. Perhaps you'd get better info from the octave mailing list, which is frequented by the maintainers (SO is not so much).
    – Tasos Papastylianou
    Nov 20 at 9:37










  • @RobertF might be worth opening a bug. I had hopes for using 'xdatasource' instead of 'xdata', but it doesn't seem to work either.
    – Tasos Papastylianou
    Nov 20 at 14:34






  • 1




    Bug report submitted savannah.gnu.org/bugs/index.php?55064
    – Robert F
    Nov 20 at 15:57
















0














I'm assuming you meant to provide a slightly more interesting animation example ... but in any case running this on my octave does not display any noticeable increase in memory usage. Perhaps, as you say, because it's a trivial animation.



However, in general, there's not much you can do for memory optimisation in octave, with the exception of avoiding to create / assign new variables if you can afford to change things in-place, since this avoids the need for allocating new memory to hold the new object. This is also the principle behind assigning index-by-index to a preallocated array in for loops, as opposed to appending an element to the end of an array at each iteration (when you 'append' to an array, you effectively need to allocate space for the now 'larger' array first).



For example, in your example above, instead of calling zeros each time (which allocates a new array in memory) and assigning this new object to 'zer', it may be more efficient to assign the result in-place to each element in the existing 'zer' itself (i.e. zer(:) = zeros(bla bla)). I cannot guarantee this is faster because it depends on how quickly octave destroys the temporary 'zeros' output compared to the unused memory that used to be held by 'zer' before its reallocation ... but it may be something that could make a difference.



The other thing you could try is rely on the fact that octave (like matlab) relies on lazy evaluation. E.g. doing A = B will not allocate new memory for A, until B changes in the meantime; at which point octave 'unlinks' A from B, and allocates space for it at that point to hold the now different array. so if at any point in your animations you find yourself initialising a lot of structures in the same way, you could initialise these with each other, and octave will not allocate extra memory for each component until it needs to. Have a look here if you're interested: https://octave.org/doc/interpreter/Miscellaneous-Techniques.html#Miscellaneous-Techniques



But, honestly though, all this is microoptimisations. Unless you're dealing with huge matrices, I doubt any of this makes a significant difference in terms of memory usage ...



EDIT



Here is some code I tried implementing the above principles (or so I hoped).





% slightly more interesting animation
planetx = 10 * cos(0.1:0.1:1500).';
planety = 10 * sin(0.1:0.1:1500).';
planetz = (planetx + planety);

% ... intermediate code as in question
% [...]

% updated while loop using above concepts
xdata = zeros(70,1); % we will be updating these in place using slices from planetx
ydata = zeros(70,1); % similarly for y and z
zdata = zeros(70,1);

while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if i < (n1 + 1)
xdata(1:i, 1) = planetx(1:i, 1);
ydata(1:i, 1) = planety(1:i, 1);
zdata(1:i, 1) = planetz(1:i, 1);
set(p1, 'xdata', xdata, 'ydata', ydata, 'zdata', zdata)
else
xdata(1 : n1+1, 1) = planetx(i-n1:i, 1);
ydata(1 : n1+1, 1) = planety(i-n1:i, 1);
zdata(1 : n1+1, 1) = planetz(i-n1:i, 1);
set(p1, 'xdatasource', 'xdata', 'ydatasource', 'ydata', 'zdatasource', 'zdata')
endif;
refreshdata;
pause(0.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


This replaced unnecessary calls resulting in temporary allocations (e.g. zeros and size calls), uses updating of preallocated arrays (e.g. xdata) instead of overwriting, and uses xdatasource, which I was hoping would be implemented as a pointer rather than as a reassignment under the hood.



Turns out it's worse memory-wise, if anything. So yeah, worth letting the octave team know. :p






share|improve this answer























  • Funny, I used the 'zer' array so that I would avoid changing the size of the 'xdata'..... for each handle but now I see I have created another source of recreating variables. I will try to work around that now because otherwise I am at the mercy of 'set'. Do you think it's possible that 'set(h,'xdata'...) really doesn't replace but just creates a new variable of the same size?
    – Robert F
    Nov 20 at 3:49










  • I tried fixing the 'zer' array problem in the edit above, but it didn't seem to fix anything.
    – Robert F
    Nov 20 at 4:57










  • well, in a sense you're allocating even more memory now: you have 6 independent 'zeros' instructions. Obviously much of this (including the behaviour of 'set') depends on any optimisations that exist und we the hood, but the idea is to assign by index to a reallocated array, avoiding new allocations. But that still seems overkill. Perhaps you'd get better info from the octave mailing list, which is frequented by the maintainers (SO is not so much).
    – Tasos Papastylianou
    Nov 20 at 9:37










  • @RobertF might be worth opening a bug. I had hopes for using 'xdatasource' instead of 'xdata', but it doesn't seem to work either.
    – Tasos Papastylianou
    Nov 20 at 14:34






  • 1




    Bug report submitted savannah.gnu.org/bugs/index.php?55064
    – Robert F
    Nov 20 at 15:57














0












0








0






I'm assuming you meant to provide a slightly more interesting animation example ... but in any case running this on my octave does not display any noticeable increase in memory usage. Perhaps, as you say, because it's a trivial animation.



However, in general, there's not much you can do for memory optimisation in octave, with the exception of avoiding to create / assign new variables if you can afford to change things in-place, since this avoids the need for allocating new memory to hold the new object. This is also the principle behind assigning index-by-index to a preallocated array in for loops, as opposed to appending an element to the end of an array at each iteration (when you 'append' to an array, you effectively need to allocate space for the now 'larger' array first).



For example, in your example above, instead of calling zeros each time (which allocates a new array in memory) and assigning this new object to 'zer', it may be more efficient to assign the result in-place to each element in the existing 'zer' itself (i.e. zer(:) = zeros(bla bla)). I cannot guarantee this is faster because it depends on how quickly octave destroys the temporary 'zeros' output compared to the unused memory that used to be held by 'zer' before its reallocation ... but it may be something that could make a difference.



The other thing you could try is rely on the fact that octave (like matlab) relies on lazy evaluation. E.g. doing A = B will not allocate new memory for A, until B changes in the meantime; at which point octave 'unlinks' A from B, and allocates space for it at that point to hold the now different array. so if at any point in your animations you find yourself initialising a lot of structures in the same way, you could initialise these with each other, and octave will not allocate extra memory for each component until it needs to. Have a look here if you're interested: https://octave.org/doc/interpreter/Miscellaneous-Techniques.html#Miscellaneous-Techniques



But, honestly though, all this is microoptimisations. Unless you're dealing with huge matrices, I doubt any of this makes a significant difference in terms of memory usage ...



EDIT



Here is some code I tried implementing the above principles (or so I hoped).





% slightly more interesting animation
planetx = 10 * cos(0.1:0.1:1500).';
planety = 10 * sin(0.1:0.1:1500).';
planetz = (planetx + planety);

% ... intermediate code as in question
% [...]

% updated while loop using above concepts
xdata = zeros(70,1); % we will be updating these in place using slices from planetx
ydata = zeros(70,1); % similarly for y and z
zdata = zeros(70,1);

while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if i < (n1 + 1)
xdata(1:i, 1) = planetx(1:i, 1);
ydata(1:i, 1) = planety(1:i, 1);
zdata(1:i, 1) = planetz(1:i, 1);
set(p1, 'xdata', xdata, 'ydata', ydata, 'zdata', zdata)
else
xdata(1 : n1+1, 1) = planetx(i-n1:i, 1);
ydata(1 : n1+1, 1) = planety(i-n1:i, 1);
zdata(1 : n1+1, 1) = planetz(i-n1:i, 1);
set(p1, 'xdatasource', 'xdata', 'ydatasource', 'ydata', 'zdatasource', 'zdata')
endif;
refreshdata;
pause(0.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


This replaced unnecessary calls resulting in temporary allocations (e.g. zeros and size calls), uses updating of preallocated arrays (e.g. xdata) instead of overwriting, and uses xdatasource, which I was hoping would be implemented as a pointer rather than as a reassignment under the hood.



Turns out it's worse memory-wise, if anything. So yeah, worth letting the octave team know. :p






share|improve this answer














I'm assuming you meant to provide a slightly more interesting animation example ... but in any case running this on my octave does not display any noticeable increase in memory usage. Perhaps, as you say, because it's a trivial animation.



However, in general, there's not much you can do for memory optimisation in octave, with the exception of avoiding to create / assign new variables if you can afford to change things in-place, since this avoids the need for allocating new memory to hold the new object. This is also the principle behind assigning index-by-index to a preallocated array in for loops, as opposed to appending an element to the end of an array at each iteration (when you 'append' to an array, you effectively need to allocate space for the now 'larger' array first).



For example, in your example above, instead of calling zeros each time (which allocates a new array in memory) and assigning this new object to 'zer', it may be more efficient to assign the result in-place to each element in the existing 'zer' itself (i.e. zer(:) = zeros(bla bla)). I cannot guarantee this is faster because it depends on how quickly octave destroys the temporary 'zeros' output compared to the unused memory that used to be held by 'zer' before its reallocation ... but it may be something that could make a difference.



The other thing you could try is rely on the fact that octave (like matlab) relies on lazy evaluation. E.g. doing A = B will not allocate new memory for A, until B changes in the meantime; at which point octave 'unlinks' A from B, and allocates space for it at that point to hold the now different array. so if at any point in your animations you find yourself initialising a lot of structures in the same way, you could initialise these with each other, and octave will not allocate extra memory for each component until it needs to. Have a look here if you're interested: https://octave.org/doc/interpreter/Miscellaneous-Techniques.html#Miscellaneous-Techniques



But, honestly though, all this is microoptimisations. Unless you're dealing with huge matrices, I doubt any of this makes a significant difference in terms of memory usage ...



EDIT



Here is some code I tried implementing the above principles (or so I hoped).





% slightly more interesting animation
planetx = 10 * cos(0.1:0.1:1500).';
planety = 10 * sin(0.1:0.1:1500).';
planetz = (planetx + planety);

% ... intermediate code as in question
% [...]

% updated while loop using above concepts
xdata = zeros(70,1); % we will be updating these in place using slices from planetx
ydata = zeros(70,1); % similarly for y and z
zdata = zeros(70,1);

while (play=='y');
for i=1:1:N
set(h, 'xdata', planetx(i,:) , 'ydata', planety(i,:), 'zdata', planetz(i,:))
title(sprintf('YEAR=%f',2000+i/N*200 ))

if i < (n1 + 1)
xdata(1:i, 1) = planetx(1:i, 1);
ydata(1:i, 1) = planety(1:i, 1);
zdata(1:i, 1) = planetz(1:i, 1);
set(p1, 'xdata', xdata, 'ydata', ydata, 'zdata', zdata)
else
xdata(1 : n1+1, 1) = planetx(i-n1:i, 1);
ydata(1 : n1+1, 1) = planety(i-n1:i, 1);
zdata(1 : n1+1, 1) = planetz(i-n1:i, 1);
set(p1, 'xdatasource', 'xdata', 'ydatasource', 'ydata', 'zdatasource', 'zdata')
endif;
refreshdata;
pause(0.001)
endfor
play=input("'y' to replay, any button to close!","s")
endwhile


This replaced unnecessary calls resulting in temporary allocations (e.g. zeros and size calls), uses updating of preallocated arrays (e.g. xdata) instead of overwriting, and uses xdatasource, which I was hoping would be implemented as a pointer rather than as a reassignment under the hood.



Turns out it's worse memory-wise, if anything. So yeah, worth letting the octave team know. :p







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 20 at 18:21

























answered Nov 20 at 0:28









Tasos Papastylianou

10.7k1931




10.7k1931












  • Funny, I used the 'zer' array so that I would avoid changing the size of the 'xdata'..... for each handle but now I see I have created another source of recreating variables. I will try to work around that now because otherwise I am at the mercy of 'set'. Do you think it's possible that 'set(h,'xdata'...) really doesn't replace but just creates a new variable of the same size?
    – Robert F
    Nov 20 at 3:49










  • I tried fixing the 'zer' array problem in the edit above, but it didn't seem to fix anything.
    – Robert F
    Nov 20 at 4:57










  • well, in a sense you're allocating even more memory now: you have 6 independent 'zeros' instructions. Obviously much of this (including the behaviour of 'set') depends on any optimisations that exist und we the hood, but the idea is to assign by index to a reallocated array, avoiding new allocations. But that still seems overkill. Perhaps you'd get better info from the octave mailing list, which is frequented by the maintainers (SO is not so much).
    – Tasos Papastylianou
    Nov 20 at 9:37










  • @RobertF might be worth opening a bug. I had hopes for using 'xdatasource' instead of 'xdata', but it doesn't seem to work either.
    – Tasos Papastylianou
    Nov 20 at 14:34






  • 1




    Bug report submitted savannah.gnu.org/bugs/index.php?55064
    – Robert F
    Nov 20 at 15:57


















  • Funny, I used the 'zer' array so that I would avoid changing the size of the 'xdata'..... for each handle but now I see I have created another source of recreating variables. I will try to work around that now because otherwise I am at the mercy of 'set'. Do you think it's possible that 'set(h,'xdata'...) really doesn't replace but just creates a new variable of the same size?
    – Robert F
    Nov 20 at 3:49










  • I tried fixing the 'zer' array problem in the edit above, but it didn't seem to fix anything.
    – Robert F
    Nov 20 at 4:57










  • well, in a sense you're allocating even more memory now: you have 6 independent 'zeros' instructions. Obviously much of this (including the behaviour of 'set') depends on any optimisations that exist und we the hood, but the idea is to assign by index to a reallocated array, avoiding new allocations. But that still seems overkill. Perhaps you'd get better info from the octave mailing list, which is frequented by the maintainers (SO is not so much).
    – Tasos Papastylianou
    Nov 20 at 9:37










  • @RobertF might be worth opening a bug. I had hopes for using 'xdatasource' instead of 'xdata', but it doesn't seem to work either.
    – Tasos Papastylianou
    Nov 20 at 14:34






  • 1




    Bug report submitted savannah.gnu.org/bugs/index.php?55064
    – Robert F
    Nov 20 at 15:57
















Funny, I used the 'zer' array so that I would avoid changing the size of the 'xdata'..... for each handle but now I see I have created another source of recreating variables. I will try to work around that now because otherwise I am at the mercy of 'set'. Do you think it's possible that 'set(h,'xdata'...) really doesn't replace but just creates a new variable of the same size?
– Robert F
Nov 20 at 3:49




Funny, I used the 'zer' array so that I would avoid changing the size of the 'xdata'..... for each handle but now I see I have created another source of recreating variables. I will try to work around that now because otherwise I am at the mercy of 'set'. Do you think it's possible that 'set(h,'xdata'...) really doesn't replace but just creates a new variable of the same size?
– Robert F
Nov 20 at 3:49












I tried fixing the 'zer' array problem in the edit above, but it didn't seem to fix anything.
– Robert F
Nov 20 at 4:57




I tried fixing the 'zer' array problem in the edit above, but it didn't seem to fix anything.
– Robert F
Nov 20 at 4:57












well, in a sense you're allocating even more memory now: you have 6 independent 'zeros' instructions. Obviously much of this (including the behaviour of 'set') depends on any optimisations that exist und we the hood, but the idea is to assign by index to a reallocated array, avoiding new allocations. But that still seems overkill. Perhaps you'd get better info from the octave mailing list, which is frequented by the maintainers (SO is not so much).
– Tasos Papastylianou
Nov 20 at 9:37




well, in a sense you're allocating even more memory now: you have 6 independent 'zeros' instructions. Obviously much of this (including the behaviour of 'set') depends on any optimisations that exist und we the hood, but the idea is to assign by index to a reallocated array, avoiding new allocations. But that still seems overkill. Perhaps you'd get better info from the octave mailing list, which is frequented by the maintainers (SO is not so much).
– Tasos Papastylianou
Nov 20 at 9:37












@RobertF might be worth opening a bug. I had hopes for using 'xdatasource' instead of 'xdata', but it doesn't seem to work either.
– Tasos Papastylianou
Nov 20 at 14:34




@RobertF might be worth opening a bug. I had hopes for using 'xdatasource' instead of 'xdata', but it doesn't seem to work either.
– Tasos Papastylianou
Nov 20 at 14:34




1




1




Bug report submitted savannah.gnu.org/bugs/index.php?55064
– Robert F
Nov 20 at 15:57




Bug report submitted savannah.gnu.org/bugs/index.php?55064
– Robert F
Nov 20 at 15:57


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53355594%2fupdating-plot-in-gnu-octave-consumes-memory%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

If I really need a card on my start hand, how many mulligans make sense? [duplicate]

Alcedinidae

Can an atomic nucleus contain both particles and antiparticles? [duplicate]