Как избежать сбоя MATLAB при открытии слишком большого числа фигур?
Иногда я запускаю скрипт MATLAB и слишком поздно осознаю, что он будет выводить слишком много цифр. В конце концов я получаю
Исключение в потоке "AWT-EventQueue-0" java.lang.OutOfMemoryError: пространство кучи Java
которые могут быть легко воспроизведены на моей машине с помощью
for i=1:inf
figure;
end
Я получаю около 90 цифр, прежде чем он падает, со стандартной настройкой ( Preferences / Java Heap Memory) 128 МБ кучи Java, а удвоение кучи до 256 МБ дает мне около 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
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 ответа
В общем, я бы рекомендовал установить максимальную память кучи Java примерно на 25% доступной оперативной памяти, что позволяет открывать много цифр (но не бесконечных чисел). Если вы не можете сделать это в настройках (например, b/c у вас Mac, как у меня), это решение поможет - оно переопределяет настройки предпочтений.
Связанное решение также сообщает вам, сколько свободной памяти Java у вас осталось, и сколько всего доступно: Выполните следующие команды:
java.lang.Runtime.getRuntime.maxMemory
java.lang.Runtime.getRuntime.totalMemory
java.lang.Runtime.getRuntime.freeMemory
К сожалению, для фигуры не требуется фиксированный объем памяти Java, для пустой фигуры требуется гораздо меньше, чем 10 тыс. Точек, а для минимизированной фигуры требуется меньше памяти, чем для максимизированной. Однако, если вы можете оценить средний объем памяти, необходимый для каждого рисунка, вы действительно можете написать оболочку для figure
который проверяет, вероятно ли, что эта цифра будет последней. Альтернативно / дополнительно, вы можете сделать функцию-обертку минимизировать все другие фигуры ( см. Недокументированный Matlab для этого).
РЕДАКТИРОВАТЬ Как указал @Peter Lawrey, вы также можете попробовать выполнить сборку мусора, прежде чем проверять, сколько памяти доступно - хотя я не знаю, попытается ли Matlab это сделать, в любом случае.
Вы можете проверить свободную память, если не хватает триггера GC и проверить еще раз. Если там все еще недостаточно, потерпите неудачу. Возможно, вы захотите выделить 1-10 МБ свободного места.
Вы можете использовать Runtime.gc() и Runtime.freeMemory();
Если вы не установите максимальный объем памяти, он будет равен проценту доступной памяти.
Я использую функцию 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.