Skip to content
  • Alan Wu's avatar
    68ffc8db
    Set allocator on class creation · 68ffc8db
    Alan Wu authored
    Allocating an instance of a class uses the allocator for the class. When
    the class has no allocator set, Ruby looks for it in the super class
    (see rb_get_alloc_func()).
    
    It's uncommon for classes created from Ruby code to ever have an
    allocator set, so it's common during the allocation process to search
    all the way to BasicObject from the class with which the allocation is
    being performed. This makes creating instances of classes that have
    long ancestry chains more expensive than creating instances of classes
    have that shorter ancestry chains.
    
    Setting the allocator at class creation time removes the need to perform
    a search for the alloctor during allocation.
    
    This is a breaking change for C-extensions that assume that classes
    created from Ruby code have no allocator set. Libraries that setup a
    class hierarchy in Ruby code and then set the allocator on some parent
    class, for example, can experience breakage. This seems like an unusual
    use case and hopefully it is rare or non-existent in practice.
    
    Rails has many classes that have upwards of 60 elements in the ancestry
    chain and benchmark shows a significant improvement for allocating with
    a class that includes 64 modules.
    
    ```
    pre: ruby 3.0.0dev (2020-11-12T14:39:27Z master 63258664)
    post: ruby 3.0.0dev (2020-11-12T20:15:30Z cut-allocator-lookup)
    
    Comparison:
                      allocate_8_deep
                    post:  10336985.6 i/s
                     pre:   8691873.1 i/s - 1.19x  slower
    
                     allocate_32_deep
                    post:  10423181.2 i/s
                     pre:   6264879.1 i/s - 1.66x  slower
    
                     allocate_64_deep
                    post:  10541851.2 i/s
                     pre:   4936321.5 i/s - 2.14x  slower
    
                    allocate_128_deep
                    post:  10451505.0 i/s
                     pre:   3031313.5 i/s - 3.45x  slower
    ```
    68ffc8db
    Set allocator on class creation
    Alan Wu authored
    Allocating an instance of a class uses the allocator for the class. When
    the class has no allocator set, Ruby looks for it in the super class
    (see rb_get_alloc_func()).
    
    It's uncommon for classes created from Ruby code to ever have an
    allocator set, so it's common during the allocation process to search
    all the way to BasicObject from the class with which the allocation is
    being performed. This makes creating instances of classes that have
    long ancestry chains more expensive than creating instances of classes
    have that shorter ancestry chains.
    
    Setting the allocator at class creation time removes the need to perform
    a search for the alloctor during allocation.
    
    This is a breaking change for C-extensions that assume that classes
    created from Ruby code have no allocator set. Libraries that setup a
    class hierarchy in Ruby code and then set the allocator on some parent
    class, for example, can experience breakage. This seems like an unusual
    use case and hopefully it is rare or non-existent in practice.
    
    Rails has many classes that have upwards of 60 elements in the ancestry
    chain and benchmark shows a significant improvement for allocating with
    a class that includes 64 modules.
    
    ```
    pre: ruby 3.0.0dev (2020-11-12T14:39:27Z master 63258664)
    post: ruby 3.0.0dev (2020-11-12T20:15:30Z cut-allocator-lookup)
    
    Comparison:
                      allocate_8_deep
                    post:  10336985.6 i/s
                     pre:   8691873.1 i/s - 1.19x  slower
    
                     allocate_32_deep
                    post:  10423181.2 i/s
                     pre:   6264879.1 i/s - 1.66x  slower
    
                     allocate_64_deep
                    post:  10541851.2 i/s
                     pre:   4936321.5 i/s - 2.14x  slower
    
                    allocate_128_deep
                    post:  10451505.0 i/s
                     pre:   3031313.5 i/s - 3.45x  slower
    ```
Loading