A peek behind the Ruby curtain: exploring object_id

Yoichi Michael Nagano
4 min readApr 18, 2020

Before I started to learn about computer programming, I was intimidated by the belief that I would need a much deeper understanding of how computers worked before I was able to do anything remotely useful. And while months of self-study and a few weeks of an intensive training program has indeed deepened my understanding, I’ve come to better appreciate that programming languages are like myriad other tools of modernity: one can competently use them without deeply understanding how they work. (And isn’t that genuinely great?) At this point in my education, perhaps in particular, I often muse about how much I’ve learned but how little I feel I understand. I am referring less to language syntax than I am to the underlying structures of programming languages.

To use Ruby as an example, what allows our computer to understand instructions that are written in a from quite strikingly close to English? At the most basic, electro-chemical level, what is happening to represent these words? I’m incapable of answering that question, (for now) but I have started to get a glimpse of some of that underlying functionality. While learning about object instances in Ruby, I was introduced to the “object id,” a unique number assigned to objects created during the run of a program. These “ids” are places in free computer memory Ruby has instructed your computer to “store” these objects. Create an object and Ruby will find a place to store it.

Even if your interest in computers and how they function is limited to knowing how to properly use a handful of useful applications, you’ve likely had a passing thought about how they are able to store all the information they contain. The ubiquity of computer and mobile devices is such that the majority of us very basically comprehend that when we look at a picture on a computer’s screen we are not looking at a physical picture. The specifics of how it is able to present this picture in photo-realistic quality seem inscrutable, but it is generally understood that a smartphone contains instructions that its screen uses to light itself in a manner that reproduces an image.

The “instructions” for sound on a vinyl record are easier to grasp: the microscopic variances in shape to the grooves on a record’s surface directly correspond to variance in air vibrations our ears sense as sound. (Computer discs of different varieties function similarly in that they are “read” by their “grooves”) Try putting your ear close to a playing record’s surface. Most of what your stereo system is doing is simply amplifying that sound.

Back to computers, inside your computer’s storage Ruby has reserved space for its own data. I won’t be getting into the form this data takes in storage, but rather the interesting way in which Ruby stores to. As mentioned above, every object created in a Ruby program gets assigned a unique id that references its location in storage. You can play around with this in your computer’s terminal using Ruby’s REPL, irb.

An object is created, it gets an id. Note that for “hello,” that id is temporary. Were we to exit the REPL, re-enter and create a “hello” object, it would be assigned a different id. However, some objects have permanently assigned ids. These include the objects true, false, nil and integers. Looking up their object_ids return some surprising results.

“True” is assigned 20, “false” 0, and “nil” 8. Earlier versions of Ruby apparently assigned them differently: “true” was 2 and nil was 4. Doing some light reading, I learned the update had to do with performance enhancement, but the details of how this rearrangement contributes to better functioning are still beyond me. What is slightly more comprehensible is the methodology of assigning ids to integers. You’ll notice a pattern. The id of 1 points to the 0. The id of 3 points to 1. The id of 5 points to 2. Testing with other integers, we can extrapolate an integer’s id corresponds to the addition of 1 to their doubled value, i.e. (i*2+1). In other, other words, odd-numbered ids are reserved for integers.

The reason for this is easier to understand, and we can see this in action from playing around in irb some more. What do you notice about all the object ids of the objects created in the left Ruby session? They’re all even numbers. The even-numbered ids in Ruby are reserved for the all the objects the user creates. By this method, Ruby can reserve holding space for any new objects created while retaining permanent spaces for certain objects, including a staggering number of integers.

This is a shallow dive into the mechanics and function of computer storage, but I felt it to be the first time I was able to both understand the methodology and see it in action.

--

--

Yoichi Michael Nagano

Full Stack Software Engineer, film camera lover, Brooklyn resident.