2012-05-03 8 views
8

Ho notato che gli oggetti hanno i loro ID assegnati in modo poco intuitivo. Prima viene creato un oggetto, maggiore è l'ID dell'oggetto. Avrei pensato che sarebbero stati assegnati in ordine crescente, piuttosto che il contrario.Perché Ruby tende ad assegnare gli ID oggetto in ordine decrescente?

Ad esempio:

obj1 = Object.new 
obj2 = Object.new 
obj3 = Object.new 

p obj1.object_id # => 4806560 
p obj2.object_id # => 4806540 
p obj3.object_id # => 4806520 

Perché sono assegnati in modo tale e anche perché c'è una fase di 20, invece di 1 nel codice gestito dall'interprete Ruby, ma di gran lunga più grande differenza tra oggetto ID per il codice eseguito da Ruby's irb?

+1

'object_id' è solo un numero intero che identifica univocamente un oggetto, qualsiasi ordine particolare che pensi di vedere è puramente un artefatto di implementazione. –

+0

@theTinMan Shaving Yak? No, sto cercando di soddisfare una curiosità. – Matty

risposta

14

handwaving nel corso di molti dettagli, rubino assegna un pezzo del mucchio di mettere gli oggetti in:

1 | 2 | 3 | 4 | 5 

attraversa quindi loro in ordine e li aggiunge ad una lista concatenata di oggetti liberi. Questo li porta ad essere in ordine inverso sulla lista concatenata:

freelist → NULL 
freelist → 1 → NULL 
freelist → 2 → 1 → NULL 
freelist → 3 → 2 → 1 → NULL 
freelist → 4 → 3 → 2 → 1 → NULL 
freelist → 5 → 4 → 3 → 2 → 1 → NULL 

Nell'assegnazione rubino oggetto utilizza la prima voce della lista collegata:

object = freelist 
freelist = object.next_free 

Così il freelist ora assomiglia a:

freelist → 4 → 3 → 2 → 1 → NULL 

e ulteriori oggetti allocati verranno visualizzati in ordine inverso su piccole allocazioni.

Quando ruby ​​deve allocare una nuova porzione di heap per archiviare più oggetti, vedrete che object_id salta in alto e poi si scarica di nuovo.

2

L'interprete Ruby è un programma in C, probabilmente stai guardando gli indirizzi di memoria corrispondenti degli oggetti.

0

Ho appena eseguito un registro di oggetti id, e sembrava che anche se le cose fossero andate bene, la raccolta dei rifiuti sembrava far andare le cose nell'altro modo ogni tanto. Ho visto dei salti da 20 a 80, quindi sembra essere quasi casuale. Ma con la quantità di oggetti interni mantenuti da Ruby, gli ordini ID oggetto non dipendono da nulla. Potrebbe anche essere che Ruby inizi nella parte superiore della piattaforma locale int o short per consentire un facile test per l'esecuzione (if(current_id==0) { problem }). Da quello che ho visto dai nostri vari numeri, sembra essere completamente diverso e non determinabile. Sembra (quasi) mi sembra che Ruby potrebbe anche usare il puntatore all'oggetto, perché questo è unico e garantito, e spiegherebbe le enormi lacune (20 byte) tra gli oggetti. Quando guardo il valore restituito da object_id e lo guardo accanto alla dimensione del puntatore nativo del mio sistema (Intel a 64 bit).

Ho appena eseguito un programma di test C++ sullo stesso sistema che ha stampato un puntatore su un int. Il puntatore (in decimale) era 140734848324996 e l'id oggetto Ruby era 70118105405380. I numeri non hanno molto in comune, ma sono entrambi nella stessa gamma e assomigliano a dei puntatori.

Ovviamente, se qualcuno scavasse nella fonte Ruby e lo scoprisse, sarebbe la risposta definitiva. Sto provando.

2

Per quello che vale, è possibile vedere una progressione completamente diversa su diverse implementazioni; ognuno assegna i propri oggetti in un modo diverso, con secchi di dimensioni diverse.

MRI 1.9.3

objs = [Object.new, Object.new, Object.new] 
objs.each {|o| puts o.object_id} 
# 70257700803740 
# 70257700803700 
# 70257700803680 

jruby

objs = [Object.new, Object.new, Object.new] 
objs.each {|o| puts o.object_id} 
# 2048 
# 2050 
# 2052 

RBX

objs = [Object.new, Object.new, Object.new] 
objs.each {|o| puts o.object_id} 
# 3920 
# 3924 
# 3928 
Problemi correlati