如何避免MATLAB在打开太多数字时崩溃?

2022-09-03 15:40:25

有时我启动一个 MATLAB 脚本,却意识到它输出的数字太多了,为时已晚。最终我得到了一个

线程 “AWT-EventQueue-0” java.lang.OutOfMemoryError 中的异常: Java 堆空间

这可以轻松地在我的机器上复制

for i=1:inf
  figure;
end

在它崩溃之前,我得到了大约90个数字,标准设置(首选项/Java堆内存)为128 MB Java堆,而将堆翻倍到256 MB给了我大约200个数字。

你看到任何方法来避免Java错误消息吗?如果没有足够的内存来容纳另一个数字,我希望我的脚本被告知而不是崩溃。

也许我可以有一个包装器(以某种方式?)检查有多少Java堆可用,如果没有足够的空间,它会拒绝打开一个新图形?figure

更新

使用下面的答案,我得到了一个很好的图表,说明Java有多少可用内存:

figure;plot(freeMem/1E6,'x');ylabel('java.lang.Runtime.getRuntime.freeMemory [MB]');xlabel('number of empty figures created');

这是使用

for i=1:inf
    java.lang.Runtime.getRuntime.gc
    fprintf('%3.0f: %1.0f Byte free\n',i,java.lang.Runtime.getRuntime.freeMemory);
    figure;
end

我假设开始时的增加意味着垃圾回收每次调用它时只做一定的努力?

更新 2 - 我的解决方案

使用我在这里获得的帮助,我实现了以下解决方案,作为重载并调用内置命令的解决方案:figure.mfigure

function varargout=figure(varargin)
memcutoff = 10E6; % keep at least this amount of bytes free
memkeyboard= 3E6; % if memory drops below this, interrupt execution and go to keyboard mode
global refuse_new_figures
if refuse_new_figures
    warning('jb:fig:lowjavamem2','Java WAS memory low -> refusing to create a new figure. To reset, type "global refuse_new_figures ; refuse_new_figures = [];"');
    return
end
freemem=java.lang.Runtime.getRuntime.freeMemory;
if freemem < memcutoff 
    fprintf('Free memory is low (%1.0f Bytes) -> running garbace collector...\n',freemem);
    java.lang.Runtime.getRuntime.gc
end
freemem=java.lang.Runtime.getRuntime.freeMemory;
% fprintf('Free memory is %1.0f Bytes.\n',freemem);
if freemem < memkeyboard
    warning('jb:fig:lowjavamem','Java memory very low -> going into interactive mode. Good luck!');
    keyboard;
end
if freemem < memcutoff
    warning('jb:fig:lowjavamem','Java memory low -> refusing to create a new figure!');
    refuse_new_figures=true;
else
    if nargin > 0
        if nargout > 0
            varargout{1}=builtin('figure',varargin{:});
        else
            builtin('figure',varargin{:});
        end
    else
        if nargout > 0
            varargout{1}=builtin('figure');
        else
            builtin('figure');
        end
    end
end

答案 1

一般来说,我建议将最大Java堆内存设置为可用RAM的25%左右,这允许您打开大量数字(但不是无限数字)。如果您无法在首选项中执行此操作(例如,b / c您拥有像我这样的Mac),则此解决方案将有所帮助 - 它将覆盖首选项设置。

链接的解决方案还会告诉您还剩下多少可用 java 内存,以及有多少可用内存:运行以下命令:

java.lang.Runtime.getRuntime.maxMemory
java.lang.Runtime.getRuntime.totalMemory
java.lang.Runtime.getRuntime.freeMemory 

不幸的是,一个图不需要固定数量的Java内存,一个空的图需要比显示10k个点的图少得多,一个最小化的图比最大化的图需要更少的内存。但是,如果您可以估计每个数字所需的平均内存,则确实可以编写一个包装器,用于检查此数字是否可能是最后一个。或者/另外,您可以使包装器功能最小化所有其他图形(请参阅未记录的Matlab)。figure

编辑正如@Peter Lawrey所指出的那样,在检查有多少内存可用之前,您也可以尝试执行垃圾回收 - 尽管我不知道Matlab是否会尝试这样做。


答案 2

您可以检查可用内存,如果没有足够的触发GC并再次检查。如果仍然不够,那就失败。您可能希望允许 1-10 MB 的头部空间。

您可以使用 Runtime.gc() 和 Runtime.freeMemory();

如果未设置最大内存,则将使其成为可用内存的百分比。


推荐