Как избежать сбоя MATLAB при открытии слишком большого числа фигур? - PullRequest
15 голосов
/ 01 июня 2011

Иногда я запускаю скрипт MATLAB и слишком поздно осознаю, что он будет выводить слишком много цифр.В конце концов я получаю исключение

в потоке "AWT-EventQueue-0" java.lang.OutOfMemoryError: пространство кучи Java

, которое можно легко воспроизвести на моем компьютере с помощью

for i=1:inf
  figure;
end

Я получаю около 90 цифр, прежде чем он падает, со стандартной настройкой ( Предпочтения / Память кучи Java ) 128 МБ кучи Java, при этом удвоение кучи до 256 МБ даетмне около 200 фигур.

Видите ли вы какой-либо способ избежать сообщения об ошибке Java? Если для другой фигуры недостаточно памяти, я бы хотел, чтобы мой сценарий был сказал , а не сбой.

Может быть, я мог бы иметь оболочку для figure, которая (каким-то образом?) Проверяет, сколько Java-кучи доступно, и которая отказывается открывать новую фигуру, если не хватает места?

Обновление

Используя ответы ниже, я получаю хороший график того, сколько свободной памяти имеет 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.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
            varargout{1}=builtin('figure',varargin{:});
        else
            builtin('figure',varargin{:});
        end
    else
        if nargout > 0
            varargout{1}=builtin('figure');
        else
            builtin('figure');
        end
    end
end

Ответы [ 3 ]

6 голосов
/ 01 июня 2011

В общем, я бы рекомендовал установить максимальную память кучи Java примерно на 25% доступной оперативной памяти, что позволяет открывать множество цифр (но не бесконечных чисел). Если вы не можете сделать это в настройках (например, у вас есть такой же Mac, как у меня), поможет это решение - оно отменяет настройки предпочтений.

Связанное решение также сообщает вам, сколько свободной памяти Java у вас осталось, и сколько всего доступно: Выполните следующие команды:

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

К сожалению, для фигуры не требуется фиксированный объем памяти Java, для пустой фигуры требуется гораздо меньше, чем для отображения 10 тыс. Точек, а для минимизированной фигуры требуется меньше памяти, чем для максимизированной. Однако, если вы можете оценить средний объем памяти, необходимый для каждой фигуры, вы действительно можете написать оболочку для figure, которая проверяет, будет ли эта цифра последней. В качестве альтернативы / дополнительно, вы можете заставить функцию-оболочку минимизировать все остальные цифры ( см. Недокументированный Matlab для этого).

РЕДАКТИРОВАТЬ Как указал @ Peter Lawrey , вы также можете попробовать выполнить сборку мусора перед проверкой объема доступной памяти - хотя я не знаю, попытается ли Matlab это, во всяком случае.

2 голосов
/ 01 июня 2011

Вы можете проверить свободную память, если не хватает триггера ГХ и проверить еще раз. Если там все еще недостаточно, потерпите неудачу. Возможно, вы захотите выделить 1-10 МБ свободного места.

Вы можете использовать Runtime.gc () и Runtime.freeMemory ();

Если вы не установите максимальный объем памяти, он станет процентом доступной памяти.

1 голос
/ 16 августа 2016

Я использую функцию findobj в своей собственной функции 'limfig', где 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.

...