I've noticed that objects have their IDs assigned in a counterintuitive fashion. The earlier an object is created, the greater its object ID. I would have thought they would have been assigned in ascending order, rather than the other way around.
For example:
obj1 = Object.new
obj2 = Object.new
obj3 = Object.new
p obj1.object_id # => 4806560
p obj2.object_id # => 4806540
p obj3.object_id # => 4806520
Why are they assigned in such a way and also why is there a step of 20, rather than 1 in code run by the Ruby interpreter, but a vastly greater difference between object IDs for code run by Ruby's irb?
Handwaving over many details, ruby allocates a chunk of the heap to put objects in:
1 | 2 | 3 | 4 | 5
Then traverses them in-order and adds them to a linked-list of free objects. This causes them to be in reverse order on the linked-list:
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
When allocating an object ruby uses the first item on the linked list:
object = freelist
freelist = object.next_free
So the freelist now looks like:
freelist → 4 → 3 → 2 → 1 → NULL
and further allocated objects will appear in reverse order across small allocations.
When ruby needs to allocate a new chunk of heap to store more objects you'll see the object_id jump up then run down again.