为什么Ruby倾向于按降序分配对象ID?

Mat*_*tty 8 ruby irb object-identity

我注意到对象的ID是以违反直觉的方式分配的.创建对象越早,其对象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
Run Code Online (Sandbox Code Playgroud)

为什么以这种方式分配它们以及为什么在Ruby解释器运行的代码中有20步而不是1步,但Ruby的irb运行的代码的对象ID之间的区别大得多?

drb*_*ain 14

通过处理许多细节,ruby分配了一大块堆来放置对象:

1 | 2 | 3 | 4 | 5
Run Code Online (Sandbox Code Playgroud)

然后按顺序遍历它们并将它们添加到自由对象的链接列表中.这导致它们在链表上的顺序相反:

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
Run Code Online (Sandbox Code Playgroud)

分配对象时,ruby使用链表上的第一项:

object = freelist
freelist = object.next_free
Run Code Online (Sandbox Code Playgroud)

所以freelist现在看起来像:

freelist ? 4 ? 3 ? 2 ? 1 ? NULL
Run Code Online (Sandbox Code Playgroud)

并且进一步分配的对象将在小分配中以相反的顺序出现.

当ruby需要分配一大堆堆来存储更多对象时,你会看到object_id跳起来然后再次运行.