PMPV

루비에서 object id는 왜 홀수일까? 본문

Ruby on Rails/ruby koan

루비에서 object id는 왜 홀수일까?

playinys 2018. 1. 22. 22:19
반응형

호기심쟁이 제이지


about_objects.rb:33:in 'test_small_integers_have_fixed_ids'

루비에서 정수의 object id는 왜 홀수일까?

object id가 뭘까?

이리저리 구글링을 해보다 루비와 object id에 대해 가장 잘 정리되어있는 문서를 찾았다.

주절주절 써놓은 포스팅이 필요 없다면 이 문서를 보는게 현명할듯.

http://www.sarahmei.com/blog/2009/04/21/object-ids-and-fixnums/


1.

오늘의 포스팅은 루비의 object id

나는 무심코 넘어간 문제에서 질문이 들어왔다. 호기심쟁이 제이지의 질문을 해결해 주기 위해 구글링 시작.

첫 번째 검색 키워드는 ruby integer fixed id


구글님 날 보고있다면 정답을 알려줘


역시나 줄줄 나온다. 내가 가지고 있는 모든 질문에 대한 답을 가지고 있는 갓-구글

또 역시나 영어문서만 줄줄 나온다. 언젠가 영어 공부를 하긴 해야되는데

첫 번째 링크 스택오버플로우 질문부터 보겠슴


영어공부 합시다 (언젠간)


나는 영어를 못하지만 구글 번역 확장 프로그램이 있으니까

질문은 다음과 같다.


nil, true 또는 false와 같은 시스템 객체가 Ruby에서 고정 객체 ID를 가지는 이유는 무엇입니까?

 또한 숫자의 객체 ID를 인쇄 해 보았습니다. 그것들은 동일하고 홀수 번째 시퀀스 패턴을 따르고 있습니다.

 이것에 대한 설명?


구글 번역의 자연스러움은 거의 완벽하다. 읽기 어렵지 않음

딱 하나 있는 대답은 다음과 같다.


다음 두 링크는 ​​Ruby의 객체 ID 개념을 설명합니다.


http://www.oreillynet.com/ruby/blog/2006/01/the_ruby_value_1.html

http://www.oreillynet.com/ruby/blog/2006/02/ruby_values_and_object_ids.html


오브젝트 ID는 오브젝트 값과 몇 가지 추가 정보로 계산됩니다. 

이 계산을 통해 예제에서 볼 수있는 값을 얻을 수 있습니다.


false, true, nil에도 object id가 붙어있음을 알 수 있다.

저 링크로 이동해서 문서를 읽어보겠습니다.


빌게이츠나 폰 노이만이 한국 사람이었어야 했는데.



2.

여기서 새로운 블로그를 찾았다.

ruby koan으로 공부 하는 사람의 블로그 같은데, 저 문서를 발췌해서 정리해놓은듯.


http://thepaulrayner.com/blog/2013/02/06/object-ids-in-ruby/


요 정리 속에서 내가 찾던 질문에 대한 몇 가지 대답이 있었다.


In MRI the object_id of an object is the same as the VALUE that represents the object on the C level. For most kinds of objects this VALUE is a pointer to a location in memory where the actual object data is stored. Obviously this will be different during multiple runs because it only depends on where the system decided to allocate the memory, not on any property of the object itself.


However for performance reasons true, false, nil and Fixnum`s are handled specially. For these objects there isn’t actually a struct with the object’s data in memory. All of the object’s data is encoded in the `VALUE itself. As you already figured out the values for false, true, nil and any Fixnum i, are 0, 2, 4 and i*2+1 respectively.


The reason that this works is that on any systems that MRI runs on, 024 and i*2+1 are never valid addresses for an object on the heap, so there’s no overlap with pointers to object data.


이 세 문단은 여기의 스택오버플로우 질문에서 발췌한듯.


내용을 정리해보자면,


1. MRI (Matz' Ruby Implementation)에서, object id는 실제 객체 위치에 대한 포인터이다. 이것은 시스템이 메모리를 할당하기로 결정한 위치에 의존한다.


2. 모든 객체에는 object id가 있다. 이 id는 실제 메모리 주소와 일치하지 않는 값이고, 위치를 나타낸다고 할 수 있다.


3. 대부분의 객체는 객체가 인스턴스화 될 때, 사실상 무작위로 object id를 할당한다. 하지만 성능의 문제로, false, true, nil과 같은 일부 객체는 고정된 값을 가진다.


4, Fixnum 정수 또한 지정된 계산식에 의해 (i*2+1) 고정된 값을 가진다. 이 계산식은 무한히 많은 손님을 무한히 많은 객실에 할당하는 힐버트의 그랜드 호텔의 역설에 근거한다.


첫 번째 질문 해결! 정수의 object id는 i*2+1의 형식을 취한다고 한다. 그러니까 홀수만 나오는 거였구나

이렇게 되는 이유는 i*2+1가 힙에 있는 객체에 대해 유효한 주소가 아니기 때문에 객체 데이터에 대한 포인터와 겹치지 않기 때문이라고 한다.

이 내용을 읽어보면 object id는 포인터와 메모리 주소에 연관된 개념으로 보인다. 이 부분에 대해서 다시 찾아보기 시작했다.


3.

http://www.sarahmei.com/blog/2009/04/21/object-ids-and-fixnums/


이 링크에서 또 다른 내용을 찾았다.

C와 같이 하드웨어에 가까운 언어에서, 정수의 사이즈는 아키텍쳐의 사이즈로 결정된다. 따라서 32비트 컴퓨터의 경우, 정수는 32비트이다. 64비트 환경에서는 64비트가 될 것이다. 루비에서는 마지막 한 자리를 제외한 31자리의 비트로 값이 결정된다. 따라서 -((2**30)-1)부터 (2**30)-1)까지의 정수를 Fixnum으로 친다. 이 범위를 벗어난 수는 bignum이라고 한다. 여기에서 마지막 자리의 비트는 해당 값이 fixnum인지, 혹은 object id인지를 결정하는데, 예를 들면 다음과 같다.


00000000000000000000100


1 앞으로 28개의 0이 나오는 이 숫자는 32비트 환경에서 정수 4를 나타내는데, 이 31자리의 이진법 표기에 마지막에 0이 온다면, fixnum으로 해석하여 정수 4로 친다. 그런데 마지막에 0이 아닌 1이 온다면?


000000000000000000001001


이 경우에는 object id로 해석된다. 그런 이유로 정수 4의 object id는 9가 되는 것이다. 위에 소개된 계산식 i*2+1과 일치하는 결과이다.

또한, 모든 정수의 object id의 마지막 비트 자릿수는 1이 된다. 이런 이유로, 모든 fixnum의 object id값은 홀수가 된다. 반대로 말하자면, fixnum이 아닌 객체, 문자열 등의 모든 나머지 객체의 object id값은 짝수가 된다. irb를 켜서 확인해보면 금방 알 수 있게 될 것이다. 이는 정수가 모든 객체를 위한 공간을 차지 하지 않도록 하기 위한 설계이다.


ObjectSpace._id2ref(#{object_id})


위 명령어로 object id를 통한 객체 호출이 가능하다.

예를 들어 ObjectSpace._id2ref(3)을 입력하면 1이 리턴되는 식이다.



object id가 2,6,10인 경우의 리턴 값의 내용은 확인하지 못했다. 저건 뭘까.. 

4.

총정리.

object id는 포인터처럼 객체의 메모리 위치를 나타내는 값이다. 실제 메모리 주소와는 다르다. 객체가 인스턴스화 될 때, 거의 무작위로 할당된다.
성능상의 이유로, false, true, nil, 그리고 fixnum은 고정된 object id 값을 가진다.
fixnum의 경우는 i*2+1 이라는 계산식으로 object id가 할당된다. 이 계산식의 구조 때문에 모든 정수의 id값은 홀수일 수밖에 없다.










반응형

'Ruby on Rails > ruby koan' 카테고리의 다른 글

ruby koan 가이드 v.2  (0) 2018.02.06
inspect와 to_s는 뭐가 다른걸까?  (0) 2018.01.27
assert equal은 어디에서 나온 놈일까?  (0) 2018.01.25
Comments