打开太多图形时如何避免 MATLAB 崩溃?

Posted

技术标签:

【中文标题】打开太多图形时如何避免 MATLAB 崩溃?【英文标题】:How to avoid MATLAB crash when opening too many figures? 【发布时间】:2011-09-06 06:34:55 【问题描述】:

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

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

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

for i=1:inf
  figure;
end

在 128 MB Java 堆的标准设置 (Preferences / Java Heap Memory) 崩溃之前,我得到了大约 90 个数字,而将堆加倍到 256 MB 给了我大约 200 个数字。

你有什么办法避免 Java 错误消息吗?告诉 而不是崩溃。

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

更新

使用下面的答案,我得到了一个关于 Java 有多少可用内存的漂亮图表:

这是使用

制作的
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.m,它重载并调用内置 figure 命令:

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
            varargout1=builtin('figure',varargin:);
        else
            builtin('figure',varargin:);
        end
    else
        if nargout > 0
            varargout1=builtin('figure');
        else
            builtin('figure');
        end
    end
end

【问题讨论】:

不错的更新。如果可以的话,我会第二次投票赞成。我想知道增加是否可能是由于 Java 分配了更多内存。 【参考方案1】:

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

链接的解决方案还告诉您剩余多少可用 Java 内存,以及可用的总内存量:运行以下命令:

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

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

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

【讨论】:

freeMemory 只告诉你现在有多少是免费的,而不是如果你执行一次 GC 会有多少是免费的。【参考方案2】:

您可以检查空闲内存,如果没有足够的触发GC并再次检查。如果还不够,就失败。您可能希望留出 1-10 MB 的空间。

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

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

【讨论】:

GC 总是在 JVM 抛出 OutOfMemory 错误之前自动发生,因此显式调用 Runtime.gc() 并不是真正需要释放空间,但肯定有助于获得可用内存的正确数字。需要记住的一点是,VM 决定何时进行 GC,Runtime.gc() 调用并非在所有情况下都会导致垃圾收集发生。 Matlab 会设置程序可用的最大 java 内存,你所能做的就是选择这个应该是多少。【参考方案3】:

我在我自己的函数 'limfig' 中使用了 findobj 函数,其中 imglimit 设置您希望允许一次打开的图形数量。

function y=limfig
imglimit=15;
if length(findobj('type','figure'))<imglimit
    y=figure; 

else
    'too many figures already open'
    return
end
end

将此短代码保存为 limfig.m,然后在任何其他代码中使用 f=limfig 行而不是 f=figure。

【讨论】:

以上是关于打开太多图形时如何避免 MATLAB 崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

matlab gui图形界面 如何针对复选框中选中的条目在画图中legend显示

在MATLAB里如何改变生成图形的坐标间隔

如何在matlab中为图形加标注以及文字说明

如何用MATLAB GUI创建图形用户界面

如何刷新图形以避免黑屏?

matlab中mat文件怎么转化为图形文件