2011-06-01 14 views
15

A veces empiezo una secuencia de comandos MATLAB y me doy cuenta demasiado tarde de que saldrá demasiadas cifras. Con el tiempo me sale unCómo evitar la caída de MATLAB al abrir demasiadas figuras?

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

que puede ser fácilmente reproducido en mi máquina utilizando

for i=1:inf 
    figure; 
end 

llego a alrededor de ~ 90 cifras antes de que se estrelle con el ajuste estándar (Preferences/Java Heap Memory) de 128 montón MB Java, mientras que doblar el Heap a 256 MB me da alrededor de 200 figuras.

¿Ves alguna forma de evitar el mensaje de error de Java? Si no hay suficiente memoria para otra figura, me gustaría que mi secuencia de comandos fuera en en lugar de bloquearse.

Tal vez podría tener un contenedor para figure que (de alguna manera?) Comprueba cuánto montón de Java está disponible y que se niega a abrir una nueva figura si no hay suficiente espacio disponible?

actualización

Usando las respuestas a continuación, aparece un gráfico agradable para saber cómo tiene mucha memoria libre de Java:

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

Esta fue producida usando

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 

I supongamos que el aumento en el comienzo significa que la recolección de basura solo hace un cierto esfuerzo e ¿Cuánto tiempo lo llamo?

Actualización 2 - mi solución

Usando la ayuda que llegué aquí, me implementa la siguiente solución como figure.m que sobrecarga y llama a la acumulación en el figure comando:

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 
+0

Nice update. Yo votaría esto por segunda vez si pudiera. Me pregunto si el aumento podría deberse a que Java asigna más memoria. – Jonas

Respuesta

6

En general , Le sugiero que configure la memoria de montón máxima de Java en aproximadamente el 25% de la memoria RAM disponible, lo que le permite abrir muchas cifras (pero no números infinitos). Si no puede hacer esto en las preferencias (por ejemplo, b/c tiene una Mac como la mía), this solution le ayudará; anula la configuración de preferencias.

La solución ligado también le indica la cantidad de memoria libre de Java que le queda, y la cantidad total de la disponible: Ejecutar los siguientes comandos:

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

Por desgracia, una cifra no tiene una cantidad fija de La memoria Java, una figura vacía toma mucho menos de una que muestra 10k puntos, y una figura minimizada toma menos memoria que una maximizada. Sin embargo, si puede estimar la memoria promedio necesaria por figura, puede escribir un contenedor para figure que verifique si es probable que esta cifra sea la última. Alternativamente/adicionalmente, puede hacer que la función de envoltura minimice todas las demás figuras (see Undocumented Matlab para esto).

EDITAR Como ha señalado @Peter Lawrey, también puede probar y llevar a cabo la recolección de basura antes de comprobar cómo se encuentra disponible la cantidad de memoria - aunque no sé si Matlab trataría de que, de todos modos.

+3

freeMemory solo le dice cuánto es gratis ahora, no cuánto sería gratis si realizara un GC. –

2

Puede verificar la memoria libre, si no hay suficiente gatillo GC y comprobar de nuevo. Si aún no es suficiente, falla. Es posible que desee permitir 1 a 10 MB de espacio para la cabeza.

Puede usar Runtime.gc() y Runtime.freeMemory();

Si no establece la memoria máxima, se convertirá en un porcentaje de la memoria disponible.

+2

GC siempre ocurrirá automáticamente antes de que una JVM arroje un error OutOfMemory, por lo que una llamada explícita a 'Runtime.gc()' no es realmente necesaria para liberar espacio, pero seguramente ayuda a obtener cifras correctas para la memoria utilizable. Una cosa para recordar es que la VM decide cuándo GC, las llamadas 'Runtime.gc()' no causan en todos los casos una recolección de basura. – BertNase

+0

Matlab establecerá una memoria java máxima disponible para el programa, todo lo que uno puede hacer es elegir cuánto debe ser. – Jonas

1

Utilizo la función findobj en mi propia función 'limfig', donde imglimit establece la cantidad de cifras que desea que se le permita abrir a la vez.

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

else 
    'too many figures already open' 
    return 
end 
end 

Guardar este código corto como limfig.m y luego en cualquier otro código de utilizar la línea f = limfig en lugar de f = figura.

+0

Buena manera alternativa de pensar sobre el problema ... –

Cuestiones relacionadas