Sto cercando di capire quando la memoria allocata dall'heap di Ruby viene restituita al sistema operativo. Capisco che Ruby non restituisce mai la memoria allocata al suo heap, ma non sono ancora sicuro del comportamento della memoria heap. cioè quegli oggetti che non rientrano in un valore RVALUE di 40 byte.Perché questo programma Ruby non restituisce memoria heap al sistema operativo?
Considerare il seguente programma che alloca alcune stringhe grandi e quindi impone un GC importante.
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')
Esecuzione di questo programma con Ruby 2.2.3 su MRI produce il seguente output. Dopo un GC importante forzato, la dimensione dell'heap è come previsto ma l'RSS non è diminuito in modo significativo.
-------------------
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
Confrontare questi risultati con i seguenti risultati quando allociamo un oggetto di grandi dimensioni invece di molti oggetti più piccoli.
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
Prendere nota del valore RSS finale. Sembra che abbiamo liberato tutta la memoria che abbiamo assegnato per la grande stringa.
Non sono sicuro del motivo per cui il secondo esempio rilascia la memoria, ma il primo esempio non esegue l'allocazione della memoria dall'heap di Ruby. Questo è uno reference che potrebbe fornire una spiegazione, ma sarei interessato alle spiegazioni degli altri.
Anche il rilascio di memoria sul kernel ha un costo. Gli allocatori di memoria utente possono rimanere su quella memoria (privatamente) nella speranza che possa essere riutilizzato nello stesso processo e non restituirlo al kernel per l'utilizzo di in altri processi.
Iscrizione a questo thread. Sono * molto * interessato anche a questo. – dimitarvp
La differenza fondamentale è nel primo esempio, dove vengono creati 600k * nuovi * oggetti, nel secondo solo uno. Sebbene la dimensione totale dei dati * referenziati * sia la stessa, il primo esempio richiede 600 mila volte più slot per oggetti referenziati (che probabilmente non saranno mai o molto più tardi recuperati nel sistema operativo). – joanbm
Suggerirei di seguire [articolo] (http://www.sitepoint.com/ruby-uses-memory/) e collegato [spiegazione] (http://rocket-science.ru/hacking/2013/12/17/ruby-memory-pitfalls /) di 'RVALUE's. Non sono sicuro che siano del tutto corretti, solo Koichi, noto anche come ko1, potrebbe saperlo. O qualche appassionato fortemente determinato, analizzando le fonti di Ruby. – joanbm