sintaxis rails programas program ejemplos descargar como ruby memory-management mri

programas - ruby on rails download



¿Por qué este programa de Ruby no devuelve la memoria del montón al sistema operativo? (1)

Estoy tratando de entender cuándo la memoria asignada fuera del montón de Ruby se devuelve al sistema operativo. Entiendo que Ruby nunca devuelve la memoria asignada a su montón, pero todavía no estoy seguro sobre el comportamiento de la memoria fuera del montón. Es decir, aquellos objetos que no encajan en un RVALUE de 40 bytes.

Considere el siguiente programa que asigna algunas cadenas grandes y luego fuerza a un GC principal.

require ''objspace'' STRING_SIZE = 250 def print_stats(msg) puts ''-------------------'' puts msg puts ''-------------------'' puts "RSS: #{`ps -eo rss,pid | grep #{Process.pid} | grep -v grep | awk ''{ print $1,"KB";}''`}" puts "HEAP SIZE: #{(GC.stat[:heap_sorted_length] * 408 * 40)/1024} KB" puts "SIZE OF ALL OBJECTS: #{ObjectSpace.memsize_of_all/1024} KB" end def run print_stats(''START WORK'') @data=[] 600_000.times do @data << " " * STRING_SIZE end print_stats(''END WORK'') @data=nil end run GC.start print_stats(''AFTER FORCED MAJOR GC'')

Ejecutando este programa con Ruby 2.2.3 en MRI produce el siguiente resultado. Después de un GC importante forzado, el tamaño del montón es el esperado, pero el RSS no ha disminuido significativamente.

------------------- START WORK ------------------- RSS: 7036 KB HEAP SIZE: 1195 KB SIZE OF ALL OBJECTS: 3172 KB ------------------- END WORK ------------------- RSS: 205660 KB HEAP SIZE: 35046 KB SIZE OF ALL OBJECTS: 178423 KB ------------------- AFTER FORCED MAJOR GC ------------------- RSS: 164492 KB HEAP SIZE: 35046 KB SIZE OF ALL OBJECTS: 2484 KB

Compare estos resultados con los siguientes cuando asignamos un objeto grande en lugar de muchos objetos más pequeños.

def run print_stats(''START WORK'') @data = " " * STRING_SIZE * 600_000 print_stats(''END WORK'') @data=nil end ------------------- START WORK ------------------- RSS: 7072 KB HEAP SIZE: 1195 KB SIZE OF ALL OBJECTS: 3170 KB ------------------- END WORK ------------------- RSS: 153584 KB HEAP SIZE: 1195 KB SIZE OF ALL OBJECTS: 149064 KB ------------------- AFTER FORCED MAJOR GC ------------------- RSS: 7096 KB HEAP SIZE: 1195 KB SIZE OF ALL OBJECTS: 2483 KB

Tenga en cuenta el valor RSS final. Parece que hemos liberado toda la memoria que asignamos para la cadena grande.

No estoy seguro de por qué el segundo ejemplo libera la memoria, pero el primero no, ya que ambos asignan memoria fuera del montón de Ruby. Esta es una reference que podría proporcionar una explicación, pero me interesaría recibir explicaciones de otros.

Liberar la memoria de nuevo en el kernel también tiene un costo. Los asignadores de memoria de espacio de usuario pueden conservar esa memoria (en privado) con la esperanza de que puedan reutilizarse dentro del mismo proceso y no devolverla al kernel para usarla en otros procesos.


@joanbm tiene un muy buen punto aquí. Su article referencia article :

El GC de Ruby libera la memoria gradualmente, por lo que cuando haces GC en 1 gran parte de la memoria apuntada por 1 referencia, se libera todo, pero cuando hay muchas referencias, el GC libera la memoria en pequeños trozos.

Varias llamadas a GC.start liberarán más y más memoria en el primer ejemplo.

Aquí hay 2 artículos más para profundizar: