2012-05-03 6 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 
그들이하는 방식으로 할당하고도 왜 루비 인터프리터에 의해 실행 코드의 20의 단계보다는 일이 왜

하지만 객체 사이에 훨씬 더 큰 차이를 예를 들면 다음과 같습니다

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에 지금처럼 보인다

freelist → 4 → 3 → 2 → 1 → NULL 

그리고 할당 된 개체는 작은 할당을 통해 역순으로 나타납니다.

더 많은 객체를 저장하기 위해 루비가 새로운 덩어리를 할당해야 할 때, object_id가 위로 뛰어 오르고 다시 실행되는 것을 볼 수 있습니다.

2

Ruby 인터프리터는 C 프로그램이므로 아마도 객체의 해당 메모리 주소를보고있을 것입니다.

0

방금 ​​객체 ID의 로그를 실행했는데 상황이 순조롭게 진행되었지만 가비지 수집이 잠시 동안 다른 방식으로 진행되는 것처럼 보였습니다. 20에서 80으로 점프하는 것을 보았습니다. 거의 무작위로 보인다. 그러나 Ruby가 유지하는 내부 객체의 양에 따라 객체 id 명령은 아무 것도 의존하지 않습니다. 루비가 로컬 플랫폼의 int 또는 short의 맨 위에서 시작하여 ()에 대한 쉬운 테스트를 허용 할 수도 있습니다. 우리가 여러 가지 숫자에서 보았던 것에서 볼 때, 그것은 완전히 다른 것이며 결정할 수없는 것처럼 보입니다. Ruby가 객체에 대한 포인터를 사용하고있는 것처럼 보일 수도 있습니다. 객체가 고유 한 것이지 객체 사이에 큰 간격 (20 바이트)을 설명하기 때문입니다. object_id이 반환 한 값을보고 시스템의 네이티브 포인터 크기 (64 비트 인텔) 옆을 봅니다.

방금 ​​에 대한 포인터를 인쇄 한 동일한 시스템에서 테스트 C++ 프로그램을 실행했습니다. 포인터 (십진수)는 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