In our opinion,
this PR provides one of the simplest yet most performant speed improvements to Rails 7.
introduced an inline cache
for class variable reads.
This allows for values to be read from the cache instead of traversing a complex inheritance tree to resolve a class variable value.
When class variables are read,
Ruby needs to check each class in the inheritance tree to ensure that the class variable isn’t set on any other classes in the tree.
As you can imagine this becomes an O(n) problem.
As the number of nodes increases in a tree,
the read performance degrades linearly.
Let’s look at a demonstration using a class that inherits 1 module,
30 modules and finally 100 modules.
This is how Ruby performs without cache:
Now, let’s look at the performance with the cache.
On Ruby master,
including 100 modules is 8.5x slower than including 1 module.
with the cache,
there is no performance difference between including 1 module and including 100 modules!
Now let’s look at how the Rails core team bought this performance improvement to Rails.
ActiveRecord::Base.logger is a cvar that has 63 modules in the inheritance tree.
We can check it out ourselves by calling:
Opening up ActiveRecord core,
this is how logger is defined.
Since it is defined as a mattr_accessor and not a class variable,
it is unable to utilize the performance improvements introduced by the latest Ruby.