Почему Ruby имеет тенденцию присваивать идентификаторы объектов в порядке убывания?

Я заметил, что идентификаторы объектов присваиваются нелогичным образом. Чем раньше создается объект, тем больше его идентификатор объекта. Я бы подумал, что они будут назначены в порядке возрастания, а не наоборот.

Например:

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, а не 1 в коде, выполняемом интерпретатором Ruby, но гораздо большая разница между идентификаторами объектов для кода, выполняемого irb Ruby?


person Matty    schedule 03.05.2012    source источник
comment
object_id - это просто целое число, которое однозначно идентифицирует объект, любой конкретный порядок, который, по вашему мнению, вы видите, является чисто артефактом реализации.   -  person mu is too short    schedule 03.05.2012
comment
@theTinMan бреет яков? Нет, я пытаюсь удовлетворить любопытство.   -  person Matty    schedule 03.05.2012


Ответы (4)


Размахивая многими деталями, ruby ​​выделяет кусок кучи для размещения объектов:

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

При размещении объекта ruby ​​использует первый элемент связанного списка:

object = freelist
freelist = object.next_free

Итак, фрилист теперь выглядит так:

freelist → 4 → 3 → 2 → 1 → NULL

и дополнительные выделенные объекты будут отображаться в обратном порядке в небольших выделениях.

Когда ruby ​​нужно выделить новый кусок кучи для хранения большего количества объектов, вы увидите, как object_id подпрыгивает, а затем снова уменьшается.

person drbrain    schedule 03.05.2012

Интерпретатор Ruby — это программа на C, вы, вероятно, смотрите на соответствующие адреса памяти объектов.

person Erik Petersen    schedule 03.05.2012

Что бы это ни стоило, вы можете увидеть совершенно разную прогрессию в разных реализациях; каждый распределяет свои объекты по-разному, с ведрами разного размера.

МРТ 1.9.3

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

ДЖРУБИ

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
person Bill Dueber    schedule 03.05.2012

Я только что просмотрел журнал идентификаторов объектов, и мне показалось, что, хотя все идет по порядку, сборка мусора время от времени заставляла все идти по другому пути. случайный. Но с количеством внутренних объектов, которые поддерживает Ruby, порядок идентификаторов объектов не зависит от них. Также может случиться так, что Ruby запускается в верхней части int или short локальной платформы, чтобы обеспечить простой тест на исчерпание (if(current_id==0) { problem }). Из того, что я видел из наших различных номеров, это кажется совершенно другим и не поддающимся определению. Мне (почти) кажется, что Ruby может даже использовать указатель на объект, потому что он гарантированно уникален и объясняет огромные промежутки (20 байт) между объектами. Когда я смотрю на значение, возвращаемое object_id, и смотрю на него рядом с собственным размером указателя моей системы (64-битный Intel).

Я только что запустил тестовую программу на C++ в той же системе, которая вывела указатель на int. Указатель (в десятичном виде) был 140734848324996, а идентификатор объекта Ruby был 70118105405380. У чисел мало общего, но они оба находятся в одном диапазоне и выглядят как указатели.

Конечно, если кто-то покопается в исходниках Ruby и узнает, это будет верный ответ. Я пытаюсь.

person Linuxios    schedule 03.05.2012