2012-05-03 19 views
8

我注意到對象的ID是以違反直覺的方式分配的。對象創建越早,對象ID就越大。我原以爲他們會按升序分配,而不是相反。爲什麼Ruby傾向於按降序分配對象ID?

例如:

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

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

他們爲什麼以這樣的方式分配,並且也爲什麼有由Ruby解釋運行20的碼的步驟,而不是1,而是對象之間的大得多的差Ruby的irb運行的代碼的ID?

+1

'object_id'僅僅是唯一地標識對象的一個​​整數,您認爲您看到的任何特定順序純粹是一個實現工件。 –

+0

@theTinMan刮犛牛?不,我正在努力滿足好奇心。 – Matty

回答

14

Handwaving了很多細節,紅寶石分配堆的一大塊把對象:

1 | 2 | 3 | 4 | 5 

然後遍歷它們按順序,並將它們添加到免費對象的鏈接列表。這使得他們在逆序鏈表上:

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 

鏈表。當分配一個對象紅寶石使用的第一個項目:

object = freelist 
freelist = object.next_free 

所以空閒列表現在看起來像:

freelist → 4 → 3 → 2 → 1 → NULL 

並且進一步分配的對象將以相反的順序在小分配中出現。

當ruby需要分配一個新的堆塊來存儲更多的對象時,你會看到object_id跳起來然後再次運行。

2

Ruby解釋器是一個C程序,您可能正在查看對象的相應內存地址。

0

我只是跑一個日誌對象ID,它似乎是,雖然事情,爲了去,垃圾收集似乎讓事情的其他方式在while.I每一次看到來自像2080跳躍,所以它似乎幾乎是隨機的。但是,隨着Ruby維護的內部對象數量的增加,對象標識順序不值得依賴。也可能是Ruby從本地平臺的頂端開始,即intshort,以便輕鬆測試(if(current_id==0) { problem })。從我從各種數字中看到的情況看來,這是完全不同的,不可確定的。它(幾乎)在我看來像Ruby甚至可能使用指向該對象的指針,因爲這是保證唯一的,並且可以解釋對象之間巨大的差距(20個字節)。當我查看object_id返回的值時,請看我的系統本機指針大小(64位Intel)旁邊的值。

我剛剛在同一個系統上運行了一個測試C++程序,打印出一個指向int的指針。指針(十進制)爲140734848324996,Ruby對象ID爲70118105405380。這些數字沒有太多共同之處,但它們都在相同的範圍內,看起來像指針。

當然,如果有人會深入研究Ruby源代碼並找出答案,那將是明確的答案。我嘗試着。

2

對於什麼是值得的,你可以在不同的實現上看到完全不同的進程;每個人都以不同的方式分配他們的對象,使用不同大小的桶。

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 
相關問題