2013-05-09 5 views
6

Esiste un metodo per visualizzare la dimensione della memoria allocata per una classe in ruby?Dimensioni della classe in byte

Ho creato una classe personalizzata e mi piacerebbe conoscere la sua dimensione in memoria. Quindi c'è una funzione con la somiglianza di sizeof() in C?

sto semplicemente cercando di inizializzare una nuova classe in questo modo

test = MyClass.new 

e cercando di trovare un metodo per stampare la dimensione della classe che è stato assegnato alla memoria.

Questo è possibile anche in rubino?

+0

Ci sono almeno due complicazioni a questa domanda: 1) Tutte le proprietà di un oggetto sono anche oggetti di altre classi, quindi è necessario essere chiari sul fatto che siano inclusi. 2) Il numero e i tipi di variabili di istanza sono dinamici in Ruby, quindi non c'è davvero una cosa come la dimensione della memoria di una classe. Tuttavia, potresti teoricamente misurare la memoria attualmente assegnata ad un oggetto (anche se attualmente non so come, o se Ruby ti permette di farlo). –

risposta

6

Non c'è caratteristica del linguaggio che calcola la dimensione di una classe nello stesso modo come C.

La dimensione della memoria di un oggetto dipende dall'implementazione. Dipende dall'implementazione dell'oggetto della classe base. Inoltre, non è semplice stimare la memoria utilizzata. Ad esempio, le stringhe possono essere incorporate in una struttura RString se sono brevi, ma memorizzate nell'heap se sono lunghe (Never create Ruby strings longer than 23 characters).

La memoria occupata da alcuni oggetti sono stati tabulati per diverse implementazioni rubino: Memory footprint of objects in Ruby 1.8, EE, 1.9, and OCaml

Infine, la dimensione dell'oggetto può differire anche con due oggetti della stessa classe, in quanto è possibile aggiungere arbitrariamente variabili di istanza supplementari, senza hardcoding quali variabili di istanza sono presenti. Ad esempio, vedere instance_variable_get e instance_variable_set


Se si utilizza la risonanza magnetica rubino 1.9.2+, v'è un metodo che si può provare (sappiate che sta guardando solo una parte di un oggetto, questo è evidente dal fatto che interi e stringhe sembrano avere dimensioni pari a zero):

irb(main):176:0> require 'objspace' 
=> true 
irb(main):176:0> ObjectSpace.memsize_of(134) 
=> 0 
irb(main):177:0> ObjectSpace.memsize_of("asdf") 
=> 0 
irb(main):178:0> ObjectSpace.memsize_of({a: 4}) 
=> 184 
irb(main):179:0> ObjectSpace.memsize_of({a: 4, b: 5}) 
=> 232 
irb(main):180:0> ObjectSpace.memsize_of(/a/.match("a")) 
=> 80 

potete anche provare memsize_of_all (si noti che esamina l'utilizzo della memoria di tutta interprete e sovrascrivere una variabile non sembra cancellare la vecchia copia immediatamente):

irb(main):190:0> ObjectSpace.memsize_of_all 
=> 4190347 
irb(main):191:0> asdf = 4 
=> 4 
irb(main):192:0> ObjectSpace.memsize_of_all 
=> 4201350 
irb(main):193:0> asdf = 4 
=> 4 
irb(main):194:0> ObjectSpace.memsize_of_all 
=> 4212353 
irb(main):195:0> asdf = 4.5 
=> 4.5 
irb(main):196:0> ObjectSpace.memsize_of_all 
=> 4223596 
irb(main):197:0> asdf = "a" 
=> "a" 
irb(main):198:0> ObjectSpace.memsize_of_all 
=> 4234879 

Dovresti stare molto attento perché non c'è alcuna garanzia quando l'interprete Ruby eseguirà la garbage collection. Mentre è possibile utilizzarlo per test e sperimentazione, si consiglia di NON utilizzarlo in produzione!

+0

Che ne dici di questo allora. è possibile inizializzare il numero X di classi e poi tirare l'uso della memoria dell'interprete ruby ​​prima e dopo? Sto incontrando un problema in cui ogni socket nella propria discussione otterrà una singola copia di 3 delle mie classi (per la gestione dei pacchetti e così) quindi se ci sono 10 connessioni che sono 30 istanze di ciascuna delle mie classi. Mi chiedevo se questo sarebbe stato un problema di progettazione fondamentale e avrei dovuto ricodificare/pensare la gestione dei pacchetti, o se 3 classi si traducono in un uso minimo della memoria. –

+0

questo sta dando risultati interessanti, quando eseguo semplicemente 'puts ObjectSpace.memsize_of_all 'ottengo un valore stimato a' 1180174' ma quando eseguo '(0..1000) .each do | i |; t.push PacketParser.new i; fine' e' mette ObjectSpace.memsize_of_all' ottengo '920578' che è inferiore a quello che era senza inizializzare più di 3000 delle mie classi. c'è qualcosa che mi manca qui, oltre alla gestione dei rifiuti? in realtà non sta creando 3000 classi ma semplicemente facendo riferimento alle 3 classi o qualcosa del genere? –

+0

è impossibile per me rispondere - puoi controllare ogni iterazione (forse vedrai improvvise diminuzioni in alcune iterazioni). Dovresti essere consapevole del fatto che non stai allocando solo memoria per i tuoi oggetti nell'iterazione precedente. Il costruttore PacketParser e il metodo t.push possono anche allocare variabili locali che (temporaneamente) aumentano l'utilizzo della memoria. – ronalchn