Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

YJIT: Initial support for rest args #7311

Merged
merged 2 commits into from Feb 16, 2023

Conversation

jimmyhmiller
Copy link
Contributor

Here are the stats of railsbench and liquid-render before and after these changes.

As you can see many of the iseq_has_rest turned into iseq_has_rest_and_splat. That's my plan to tackle next. I don't think it should be too hard, but just wanted to keep things incremental.

Rails Bench Before
         ***YJIT: Printing YJIT statistics on exit***
method call exit reasons: 
                      iseq_has_rest     108003 (32.3%)
                          block_arg      64648 (19.3%)
                        iseq_zsuper      46081 (13.8%)
                   iseq_arity_error      28708 ( 8.6%)
                iseq_ruby2_keywords      24995 ( 7.5%)
          args_splat_cfunc_var_args      16251 ( 4.9%)
                     iseq_has_no_kw      15971 ( 4.8%)
                           kw_splat      12995 ( 3.9%)
                    iseq_has_kwrest       5294 ( 1.6%)
           iseq_missing_optional_kw       4054 ( 1.2%)
        splatarray_length_not_equal       2029 ( 0.6%)
             args_splat_cfunc_zuper       2002 ( 0.6%)
                      iseq_has_post       1986 ( 0.6%)
                     refined_method        891 ( 0.3%)
              cfunc_ruby_array_varg        653 ( 0.2%)
                           keywords        102 ( 0.0%)
    args_splat_cfunc_ruby2_keywords         62 ( 0.0%)
                    args_splat_ivar         49 ( 0.0%)
                        send_getter         12 ( 0.0%)
                      zsuper_method          9 ( 0.0%)
                args_splat_opt_call          5 ( 0.0%)
                    ivar_set_method          2 ( 0.0%)
                  bmethod_block_arg          2 ( 0.0%)
invokeblock exit reasons: 
               ifunc       5798 (56.0%)
                proc       2385 (23.0%)
     iseq_arg0_splat       2000 (19.3%)
    iseq_tag_changed        106 ( 1.0%)
              symbol         68 ( 0.7%)
invokesuper exit reasons: 
         block       4850 (98.2%)
    me_changed         87 ( 1.8%)
leave exit reasons: 
        interp_return    1852586 (97.7%)
    start_pc_non_zero      43886 ( 2.3%)
         se_interrupt         34 ( 0.0%)
getblockparamproxy exit reasons: 
    block_param_modified          3 (100.0%)
getinstancevariable exit reasons:
    megamorphic      13685 (100.0%)
setinstancevariable exit reasons:
    (all relevant counters are zero)
opt_aref exit reasons: 
    (all relevant counters are zero)
expandarray exit reasons: 
            splat       9973 (99.8%)
    rhs_too_small         22 ( 0.2%)
opt_getinlinecache exit reasons: 
    miss         11 (100.0%)
invalidation reasons: 
       constant_ic_fill       2015 (59.3%)
          method_lookup       1044 (30.7%)
    constant_state_bump        339 (10.0%)
bindings_allocations:         184
bindings_set:                   0
compiled_iseq_count:         9290
compiled_block_count:       51999
compiled_branch_count:      82406
block_next_count:           15210
defer_count:                16299
freed_iseq_count:            4060
invalidation_count:          3398
constant_state_bumps:           0
inline_code_size:         8825496
outlined_code_size:       8822420
freed_code_size:                0
code_region_size:        17694720
yjit_alloc_size:         98211797
live_page_count:             1080
freed_page_count:               0
code_gc_count:                  0
num_gc_obj_refs:            41295
object_shape_count:          2397
side_exit_count:           513493
total_exit_count:         2366079
total_insns_count:       89905782
vm_insns_count:           8771865
yjit_insns_count:        81647410
ratio_in_yjit:              90.2%
avg_len_in_yjit:             34.3
Top-20 most frequent exit ops (100.0% of exits):
    opt_send_without_block:     141965 (27.6%)
               invokesuper:     117078 (22.8%)
                      send:     104052 (20.3%)
      opt_getconstant_path:      57739 (11.2%)
               invokeblock:      37042 (7.2%)
                  opt_aref:      14088 (2.7%)
                     throw:      10587 (2.1%)
               expandarray:       9995 (1.9%)
             setlocal_WC_0:       8358 (1.6%)
                    opt_eq:       5010 (1.0%)
       getinstancevariable:       3485 (0.7%)
        getblockparamproxy:       2271 (0.4%)
               objtostring:        448 (0.1%)
          putspecialobject:        386 (0.1%)
                 opt_nil_p:        327 (0.1%)
             definesmethod:        240 (0.0%)
                checkmatch:        204 (0.0%)
                      once:        104 (0.0%)
                     leave:         35 (0.0%)
               opt_empty_p:         31 (0.0%)
Rails Bench After
         ***YJIT: Printing YJIT statistics on exit***
method call exit reasons: 
                          block_arg:     64,659 (18.3%)
            iseq_has_rest_and_splat:     52,145 (14.8%)
                        iseq_zsuper:     46,080 (13.0%)
            iseq_has_rest_and_block:     43,558 (12.3%)
                   iseq_arity_error:     30,708 ( 8.7%)
                  klass_megamorphic:     27,431 ( 7.8%)
                iseq_ruby2_keywords:     25,025 ( 7.1%)
                     iseq_has_no_kw:     17,292 ( 4.9%)
          args_splat_cfunc_var_args:     16,251 ( 4.6%)
                           kw_splat:     12,995 ( 3.7%)
                    iseq_has_kwrest:      7,320 ( 2.1%)
           iseq_missing_optional_kw:      4,054 ( 1.1%)
             args_splat_cfunc_zuper:      2,002 ( 0.6%)
                      iseq_has_post:      1,988 ( 0.6%)
                     refined_method:        891 ( 0.3%)
              cfunc_ruby_array_varg:        653 ( 0.2%)
               iseq_has_rest_and_kw:        172 ( 0.0%)
                           keywords:        102 ( 0.0%)
    args_splat_cfunc_ruby2_keywords:         62 ( 0.0%)
                    args_splat_ivar:         49 ( 0.0%)
         iseq_has_rest_and_optional:         14 ( 0.0%)
                        send_getter:         12 ( 0.0%)
                      zsuper_method:          9 ( 0.0%)
                args_splat_opt_call:          5 ( 0.0%)
                    ivar_set_method:          2 ( 0.0%)
        splatarray_length_not_equal:          2 ( 0.0%)
                  bmethod_block_arg:          2 ( 0.0%)
invokeblock exit reasons: 
      proc:      2,385 (93.2%)
    symbol:        174 ( 6.8%)
invokesuper exit reasons: 
    me_changed:      4,783 (95.0%)
         block:        254 ( 5.0%)
leave exit reasons: 
        interp_return:  1,812,675 (97.6%)
    start_pc_non_zero:     43,882 ( 2.4%)
         se_interrupt:         34 ( 0.0%)
getblockparamproxy exit reasons: 
    block_param_modified:          3 (100.0%)
getinstancevariable exit reasons:
    megamorphic:     13,685 (100.0%)
setinstancevariable exit reasons:
    (all relevant counters are zero)
opt_aref exit reasons: 
    (all relevant counters are zero)
expandarray exit reasons: 
            splat:      9,974 (99.8%)
    rhs_too_small:         22 ( 0.2%)
opt_getinlinecache exit reasons: 
    miss:         11 (100.0%)
invalidation reasons: 
       constant_ic_fill:      2,021 (59.4%)
          method_lookup:      1,045 (30.7%)
    constant_state_bump:        338 ( 9.9%)
num_send:                 13,369,456
num_send_known_class:        439,682 ( 3.3%)
num_send_polymorphic:      1,528,493 (11.4%)
bindings_allocations:              0
bindings_set:                      0
compiled_iseq_count:           9,292
compiled_block_count:         52,233
compiled_branch_count:        82,926
block_next_count:             15,307
defer_count:                  16,372
freed_iseq_count:              4,059
invalidation_count:            3,404
constant_state_bumps:              0
inline_code_size:          9,682,128
outlined_code_size:        9,680,184
freed_code_size:                   0
code_region_size:         19,365,888
live_page_count:               1,182
freed_page_count:                  0
code_gc_count:                     0
num_gc_obj_refs:              41,460
object_shape_count:            2,428
side_exit_count:             478,725
total_exit_count:          2,291,400
yjit_insns_count:         82,165,394
avg_len_in_yjit:                35.6
Top-20 most frequent exit ops (100.0% of exits):
    opt_send_without_block:    133,196 (27.8%)
               invokesuper:    104,824 (21.9%)
                      send:    100,073 (20.9%)
      opt_getconstant_path:     53,749 (11.2%)
               invokeblock:     31,243 ( 6.5%)
                  opt_aref:     14,085 ( 2.9%)
                     throw:     10,587 ( 2.2%)
               expandarray:      9,996 ( 2.1%)
             setlocal_WC_0:      8,380 ( 1.8%)
                    opt_eq:      5,009 ( 1.0%)
       getinstancevariable:      3,485 ( 0.7%)
        getblockparamproxy:      2,271 ( 0.5%)
               objtostring:        448 ( 0.1%)
          putspecialobject:        388 ( 0.1%)
                 opt_nil_p:        327 ( 0.1%)
             definesmethod:        240 ( 0.1%)
                checkmatch:        204 ( 0.0%)
                      once:        104 ( 0.0%)
                     leave:         35 ( 0.0%)
               opt_empty_p:         30 ( 0.0%)
Liquid Render Before
         ***YJIT: Printing YJIT statistics on exit***
method call exit reasons: 
                  iseq_has_rest      41416 (88.7%)
    splatarray_length_not_equal       2978 ( 6.4%)
                      block_arg       1461 ( 3.1%)
                  zsuper_method        792 ( 1.7%)
          cfunc_ruby_array_varg         34 ( 0.1%)
                    send_getter         12 ( 0.0%)
       iseq_missing_optional_kw          9 ( 0.0%)
      args_splat_cfunc_var_args          8 ( 0.0%)
                       kw_splat          3 ( 0.0%)
                ivar_set_method          1 ( 0.0%)
invokeblock exit reasons: 
                proc        334 (81.3%)
    iseq_tag_changed         77 (18.7%)
invokesuper exit reasons: 
    block         79 (100.0%)
leave exit reasons: 
        interp_return     297668 (100.0%)
    start_pc_non_zero        111 ( 0.0%)
         se_interrupt         11 ( 0.0%)
getblockparamproxy exit reasons: 
    (all relevant counters are zero)
getinstancevariable exit reasons:
    megamorphic         11 (100.0%)
setinstancevariable exit reasons:
    (all relevant counters are zero)
opt_aref exit reasons: 
    (all relevant counters are zero)
expandarray exit reasons: 
    rhs_too_small         10 (100.0%)
opt_getinlinecache exit reasons: 
    (all relevant counters are zero)
invalidation reasons: 
       constant_ic_fill        577 (81.3%)
    constant_state_bump         89 (12.5%)
          method_lookup         44 ( 6.2%)
bindings_allocations:         150
bindings_set:                   0
compiled_iseq_count:         1685
compiled_block_count:       11688
compiled_branch_count:      19097
block_next_count:            4081
defer_count:                 3831
freed_iseq_count:             556
invalidation_count:           710
constant_state_bumps:           0
inline_code_size:         1846724
outlined_code_size:       1843072
freed_code_size:                0
code_region_size:         3702784
yjit_alloc_size:         23174105
live_page_count:              226
freed_page_count:               0
code_gc_count:                  0
num_gc_obj_refs:             7821
object_shape_count:           770
side_exit_count:            67734
total_exit_count:          365402
total_insns_count:       20364975
vm_insns_count:           2483281
yjit_insns_count:        17949428
ratio_in_yjit:              87.8%
avg_len_in_yjit:             48.9
Top-18 most frequent exit ops (100.0% of exits):
    opt_send_without_block:      45508 (67.2%)
                     throw:      19099 (28.2%)
                      send:       1495 (2.2%)
      opt_getconstant_path:        748 (1.1%)
               invokeblock:        412 (0.6%)
               invokesuper:        203 (0.3%)
                    opt_eq:         88 (0.1%)
                      once:         87 (0.1%)
          putspecialobject:         37 (0.1%)
        getblockparamproxy:         11 (0.0%)
                     leave:         11 (0.0%)
                  opt_aref:         11 (0.0%)
               expandarray:         10 (0.0%)
             setlocal_WC_0:          7 (0.0%)
                  opt_ltlt:          3 (0.0%)
                checkmatch:          2 (0.0%)
                   opt_mod:          1 (0.0%)
               opt_empty_p:          1 (0.0%)
Liquid Render After
         ***YJIT: Printing YJIT statistics on exit***
method call exit reasons: 
      iseq_has_rest_and_splat:     40,610 (94.0%)
                    block_arg:      1,462 ( 3.4%)
                zsuper_method:        792 ( 1.8%)
            klass_megamorphic:        270 ( 0.6%)
        cfunc_ruby_array_varg:         34 ( 0.1%)
                  send_getter:         12 ( 0.0%)
         iseq_has_rest_and_kw:         10 ( 0.0%)
     iseq_missing_optional_kw:          9 ( 0.0%)
    args_splat_cfunc_var_args:          8 ( 0.0%)
                     kw_splat:          3 ( 0.0%)
              ivar_set_method:          1 ( 0.0%)
      iseq_has_rest_and_block:          1 ( 0.0%)
invokeblock exit reasons: 
      proc:        334 (81.3%)
    symbol:         77 (18.7%)
invokesuper exit reasons: 
    block:         79 (100.0%)
leave exit reasons: 
        interp_return:    297,480 (100.0%)
    start_pc_non_zero:        110 ( 0.0%)
         se_interrupt:         11 ( 0.0%)
getblockparamproxy exit reasons: 
    (all relevant counters are zero)
getinstancevariable exit reasons:
    megamorphic:          8 (100.0%)
setinstancevariable exit reasons:
    (all relevant counters are zero)
opt_aref exit reasons: 
    (all relevant counters are zero)
expandarray exit reasons: 
    rhs_too_small:         10 (100.0%)
opt_getinlinecache exit reasons: 
    (all relevant counters are zero)
invalidation reasons: 
       constant_ic_fill:        578 (81.0%)
    constant_state_bump:         92 (12.9%)
          method_lookup:         44 ( 6.2%)
num_send:                  3,026,363
num_send_known_class:        107,922 ( 3.6%)
num_send_polymorphic:        610,717 (20.2%)
bindings_allocations:              0
bindings_set:                      0
compiled_iseq_count:           1,685
compiled_block_count:         11,781
compiled_branch_count:        19,289
block_next_count:              4,122
defer_count:                   3,865
freed_iseq_count:                556
invalidation_count:              714
constant_state_bumps:              0
inline_code_size:          2,026,004
outlined_code_size:        2,025,124
freed_code_size:                   0
code_region_size:          4,063,232
live_page_count:                 248
freed_page_count:                  0
code_gc_count:                     0
num_gc_obj_refs:               7,856
object_shape_count:              771
side_exit_count:              63,831
total_exit_count:            361,311
yjit_insns_count:         17,948,548
avg_len_in_yjit:                49.5
Top-18 most frequent exit ops (100.0% of exits):
    opt_send_without_block:     41,728 (65.4%)
                     throw:     19,099 (29.9%)
                      send:      1,495 ( 2.3%)
      opt_getconstant_path:        749 ( 1.2%)
               invokeblock:        411 ( 0.6%)
                    opt_eq:         88 ( 0.1%)
                      once:         87 ( 0.1%)
               invokesuper:         80 ( 0.1%)
          putspecialobject:         37 ( 0.1%)
        getblockparamproxy:         11 ( 0.0%)
                     leave:         11 ( 0.0%)
               expandarray:         10 ( 0.0%)
                  opt_aref:         10 ( 0.0%)
             setlocal_WC_0:          7 ( 0.0%)
                  opt_ltlt:          4 ( 0.0%)
                checkmatch:          2 ( 0.0%)
                   opt_mod:          1 ( 0.0%)
       setinstancevariable:          1 ( 0.0%)

@matzbot matzbot requested a review from a team February 15, 2023 16:15
yjit/src/codegen.rs Outdated Show resolved Hide resolved
yjit/src/codegen.rs Outdated Show resolved Hide resolved
yjit/src/codegen.rs Outdated Show resolved Hide resolved
yjit/src/codegen.rs Outdated Show resolved Hide resolved
@jimmyhmiller jimmyhmiller force-pushed the rest-args-initial branch 2 times, most recently from e48e41e to 6596555 Compare February 15, 2023 17:32
@YurySolovyov
Copy link

Rails bench after stats don't have ratio in yjit? 🤔

@k0kubun
Copy link
Member

k0kubun commented Feb 15, 2023

I noticed it too (It happens when you build Ruby without --enable-yjit=stats or --enable-yjit=dev), but I saw the numbers on "make yjit-bench" CI jobs anyway 🙂 (91.9%92.0%)

yjit/src/codegen.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@maximecb maximecb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Jimmy 👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants