Skip to content
  • Jeremy Evans's avatar
    2217e083
    Optimize compilation of large literal arrays · 2217e083
    Jeremy Evans authored
    
    
    To avoid stack overflow, Ruby splits compilation of large arrays
    into smaller arrays, and concatenates the small arrays together.
    It previously used newarray/concatarray for this, which is
    inefficient.  This switches the compilation to use pushtoarray,
    which is much faster. This makes almost all literal arrays only
    allocate a single array.
    
    For cases where there is a large amount of static values in the
    array, Ruby will statically compile subarrays, and previously
    added them using concatarray.  This switches to concattoarray,
    avoiding an array allocation for the append.
    
    Keyword splats are also supported in arrays, and ignored if the
    keyword splat is empty.  Previously, this used newarraykwsplat and
    concatarray.  This still uses newarraykwsplat, but switches to
    concattoarray to save an allocation.  So large arrays with keyword
    splats can allocate 2 arrays instead of 1.
    
    Previously, for the following array sizes (assuming local variable
    access for each element), Ruby allocated the following number of
    arrays:
    
      1000 elements: 7 arrays
     10000 elements: 79 arrays
    100000 elements: 781 arrays
    
    With these changes, only a single array is allocated (or 2 for a
    large array with a keyword splat.
    
    Results using the included benchmark:
    
    ```
                           array_1000
                miniruby:     34770.0 i/s
       ./miniruby-before:     10511.7 i/s - 3.31x  slower
    
                          array_10000
                miniruby:      4938.8 i/s
       ./miniruby-before:       483.8 i/s - 10.21x  slower
    
                         array_100000
                miniruby:       727.2 i/s
       ./miniruby-before:         4.1 i/s - 176.98x  slower
    ```
    
    Co-authored-by: default avatarNobuyoshi Nakada <nobu@ruby-lang.org>
    2217e083
    Optimize compilation of large literal arrays
    Jeremy Evans authored
    
    
    To avoid stack overflow, Ruby splits compilation of large arrays
    into smaller arrays, and concatenates the small arrays together.
    It previously used newarray/concatarray for this, which is
    inefficient.  This switches the compilation to use pushtoarray,
    which is much faster. This makes almost all literal arrays only
    allocate a single array.
    
    For cases where there is a large amount of static values in the
    array, Ruby will statically compile subarrays, and previously
    added them using concatarray.  This switches to concattoarray,
    avoiding an array allocation for the append.
    
    Keyword splats are also supported in arrays, and ignored if the
    keyword splat is empty.  Previously, this used newarraykwsplat and
    concatarray.  This still uses newarraykwsplat, but switches to
    concattoarray to save an allocation.  So large arrays with keyword
    splats can allocate 2 arrays instead of 1.
    
    Previously, for the following array sizes (assuming local variable
    access for each element), Ruby allocated the following number of
    arrays:
    
      1000 elements: 7 arrays
     10000 elements: 79 arrays
    100000 elements: 781 arrays
    
    With these changes, only a single array is allocated (or 2 for a
    large array with a keyword splat.
    
    Results using the included benchmark:
    
    ```
                           array_1000
                miniruby:     34770.0 i/s
       ./miniruby-before:     10511.7 i/s - 3.31x  slower
    
                          array_10000
                miniruby:      4938.8 i/s
       ./miniruby-before:       483.8 i/s - 10.21x  slower
    
                         array_100000
                miniruby:       727.2 i/s
       ./miniruby-before:         4.1 i/s - 176.98x  slower
    ```
    
    Co-authored-by: default avatarNobuyoshi Nakada <nobu@ruby-lang.org>
Loading