8

我注意到对象的 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

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

4

4 回答 4

14

在处理许多细节后,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现在看起来像:

freelist → 4 → 3 → 2 → 1 → NULL

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

当 ruby​​ 需要分配一个新的堆块来存储更多对象时,您会看到 object_id 跳起来然后又跑下来。

于 2012-05-03T00:38:18.497 回答
2

Ruby 解释器是一个 C 程序,您可能正在查看对象的相应内存地址。

于 2012-05-03T00:24:15.260 回答
2

对于它的价值,您可以在不同的实现上看到完全不同的进展;每个人都以不同的方式分配他们的对象,使用不同大小的桶。

核磁共振 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
于 2012-05-03T03:59:27.417 回答
0

我刚刚运行了一个对象 id 的日志,看起来虽然事情是按顺序进行的,但垃圾收集似乎每隔一段时间就会让事情变得相反。我看到了从 like20到的跳转80,所以它似乎几乎是随机的。但是对于 Ruby 维护的内部对象的数量,对象 id 的顺序没有什么可依赖的。也可能是 Ruby 从本地平台的顶部开始,int或者short允许一个简单的测试用完(if(current_id==0) { problem })。从我从我们的各种数字中看到的,它似乎完全不同且无法确定。它(几乎)在我看来就像 Ruby 甚至可能使用指向对象的指针,因为这保证了唯一性,并且可以解释对象之间的巨大差距(20 个字节)。当我查看返回的值时object_id,然后在我系统的本机指针大小(64 位 Intel)旁边查看它。

我刚刚在同一个系统上运行了一个测试 C++ 程序,它打印出一个指向int. 指针(十进制)是140734848324996,Ruby 对象 id 是70118105405380. 这些数字没有太多共同点,但它们都在同一范围内,看起来像指针。

当然,如果有人深入研究 Ruby 源代码并找出答案,那将是明确的答案。我正在努力。

于 2012-05-03T00:32:19.907 回答