2012-05-03 13 views
8

Nesnelerin kimliklerini kontröllü bir şekilde atandığını fark ettim. Bir nesne oluşturulduğunda, nesne kimliği o kadar büyük olur. Başka bir yoldan ziyade, artan sırada atanmış olacaklarını düşünürdüm.Ruby neden nesne kimliklerini azalan sırada atayabiliyor?

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

p obj1.object_id # => 4806560 
p obj2.object_id # => 4806540 
p obj3.object_id # => 4806520 
onlar şekilde atanan ve aynı zamanda neden Ruby yorumlayıcısı tarafından işletilen kodunda 20 adım yerine 1 yoktur Neden

ancak nesne arasındaki bir ölçüde daha büyük bir fark: Örneğin

Ruby irb tarafından çalıştırılan kod kimlikleri?

+1

'object_id' benzersiz bir nesne tanımlayan sadece bir tam sayı olduğu, Gördüğünüzü düşündüğünüz herhangi bir düzen, sadece bir uygulama eseridir. –

+0

@theTinMan Tıraş yaks? Hayır, merakı tatmin etmeye çalışıyorum. – Matty

cevap

14

handwaving, yakut nesneleri koymak için yığın yığını ayırır: in-order

1 | 2 | 3 | 4 | 5 

Sonra geçtiği onları ve ücretsiz nesnelerin bağlantılı-listesine ekler. Bu bağlantılı liste üzerinde ters sırada olmalarını neden olur:

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 

bir nesne yakut tahsis bağlantılı listedeki ilk öğeyi kullanır:

:

object = freelist 
freelist = object.next_free 

Yani freelist şimdi benziyor

ve ayrılan diğer nesneler, küçük ayırmalar arasında ters sırada görünecektir.

Ruby daha fazla nesne saklamak için yeni bir yığın yığın ayırmak gerektiğinde, object_id atlama işlemini göreceksiniz, ardından tekrar aşağıya doğru koşarsınız.

2

Ruby yorumlayıcısı bir C programıdır, büyük olasılıkla nesnelerin ilgili bellek adreslerine bakıyorsunuzdur.

0

Nesne kimliklerinin bir günlüğünü çalıştırdım ve işler sıraya girmiş olsa da, çöp toplama işlerinin her seferinde bir şekilde diğer yollardan gitmesini sağlıyor gibiydi. 20'dan ile 80 arasındaki atlamaları gördüm. neredeyse rastgele görünüyor. Fakat Ruby'nin kullandığı iç nesnelerin miktarı ile, nesne kimliklerinin bağlı olduğu hiçbir şey yoktur. Ayrıca Ruby'nin bitmek için kolay bir test yapabilmesi için yerel platformun int veya short'un üst kısmında başlaması da olabilir (if(current_id==0) { problem }). Çeşitli sayılarımızdan gördüğüm kadarıyla, tamamen farklı ve belirsiz gözüküyor. Ruby (neredeyse) bana, nesnenin işaretçisini bile kullanıyor olabileceğine benziyor, çünkü bu, benzersiz bir garantidir ve nesneler arasındaki büyük boşlukları (20 bayt) açıklar. object_id tarafından döndürülen değere baktığımda, sistemimin yerel işaretçi boyutunun (64 bit Intel) yanına bakıyorum.

int işaretçisini yazdırılan aynı sistemde bir test C++ programı çalıştırdım. İşaretçi (ondalık) 140734848324996 idi ve Ruby nesne kimliği 70118105405380 idi. Sayıların pek çoğu ortak değildir, ancak ikisi de aynı aralıktadır ve işaretçiler gibi bir şeye benzemektedir.

Elbette, birileri Ruby kaynağına girip bulsaydı, bu kesin bir cevap olurdu. Deniyorum. Birçok ayrıntılar üzerinde

2

Değeri için farklı uygulamalarda tamamen farklı bir ilerleme görebilirsiniz; Herkes kendi nesnelerini farklı büyüklükteki kovalarla farklı bir şekilde tahsis eder.

MR 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 
İlgili konular