mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
679ef34586
Previously YARV bytecode implemented constant caching by having a pair of instructions, opt_getinlinecache and opt_setinlinecache, wrapping a series of getconstant calls (with putobject providing supporting arguments). This commit replaces that pattern with a new instruction, opt_getconstant_path, handling both getting/setting the inline cache and fetching the constant on a cache miss. This is implemented by storing the full constant path as a null-terminated array of IDs inside of the IC structure. idNULL is used to signal an absolute constant reference. $ ./miniruby --dump=insns -e '::Foo::Bar::Baz' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE) 0000 opt_getconstant_path <ic:0 ::Foo::Bar::Baz> ( 1)[Li] 0002 leave The motivation for this is that we had increasingly found the need to disassemble the instructions between the opt_getinlinecache and opt_setinlinecache in order to determine the constant we are fetching, or otherwise store metadata. This disassembly was done: * In opt_setinlinecache, to register the IC against the constant names it is using for granular invalidation. * In rb_iseq_free, to unregister the IC from the invalidation table. * In YJIT to find the position of a opt_getinlinecache instruction to invalidate it when the cache is populated * In YJIT to register the constant names being used for invalidation. With this change we no longe need disassemly for these (in fact rb_iseq_each is now unused), as the list of constant names being referenced is held in the IC. This should also make it possible to make more optimizations in the future. This may also reduce the size of iseqs, as previously each segment required 32 bytes (on 64-bit platforms) for each constant segment. This implementation only stores one ID per-segment. There should be no significant performance change between this and the previous implementation. Previously opt_getinlinecache was a "leaf" instruction, but it included a jump (almost always to a separate cache line). Now opt_getconstant_path is a non-leaf (it may raise/autoload/call const_missing) but it does not jump. These seem to even out. |
||
---|---|---|
.. | ||
gc | ||
lib | ||
other-lang | ||
app_answer.rb | ||
app_aobench.rb | ||
app_erb.yml | ||
app_factorial.rb | ||
app_fib.rb | ||
app_lc_fizzbuzz.rb | ||
app_mandelbrot.rb | ||
app_pentomino.rb | ||
app_raise.rb | ||
app_strconcat.rb | ||
app_tak.rb | ||
app_tarai.rb | ||
app_uri.rb | ||
array_flatten.yml | ||
array_intersection.yml | ||
array_max_float.yml | ||
array_max_int.yml | ||
array_max_str.yml | ||
array_min.yml | ||
array_sample.yml | ||
array_sample_100k_10.rb | ||
array_sample_100k_11.rb | ||
array_sample_100k__1k.rb | ||
array_sample_100k__6k.rb | ||
array_sample_100k__100.rb | ||
array_sample_100k___10k.rb | ||
array_sample_100k___50k.rb | ||
array_shift.rb | ||
array_small_and.rb | ||
array_small_diff.rb | ||
array_small_or.rb | ||
array_sort_block.rb | ||
array_sort_float.rb | ||
array_values_at_int.rb | ||
array_values_at_range.rb | ||
attr_accessor.yml | ||
bighash.rb | ||
buffer_get.yml | ||
cgi_escape_html.yml | ||
complex_float_add.yml | ||
complex_float_div.yml | ||
complex_float_mul.yml | ||
complex_float_new.yml | ||
complex_float_power.yml | ||
complex_float_sub.yml | ||
constant_invalidation.rb | ||
dir_empty_p.rb | ||
enum_lazy_flat_map.yml | ||
enum_lazy_grep_v_20.rb | ||
enum_lazy_grep_v_50.rb | ||
enum_lazy_grep_v_100.rb | ||
enum_lazy_uniq_20.rb | ||
enum_lazy_uniq_50.rb | ||
enum_lazy_uniq_100.rb | ||
enum_lazy_zip.yml | ||
enum_tally.yml | ||
erb_render.yml | ||
fiber_chain.yml | ||
fiber_locals.yml | ||
file_chmod.rb | ||
file_rename.rb | ||
float_methods.yml | ||
float_neg_posi.yml | ||
float_to_s.yml | ||
hash_aref_array.rb | ||
hash_aref_dsym.rb | ||
hash_aref_dsym_long.rb | ||
hash_aref_fix.rb | ||
hash_aref_flo.rb | ||
hash_aref_miss.rb | ||
hash_aref_str.rb | ||
hash_aref_sym.rb | ||
hash_aref_sym_long.rb | ||
hash_defaults.yml | ||
hash_dup.yml | ||
hash_first.yml | ||
hash_flatten.rb | ||
hash_ident_flo.rb | ||
hash_ident_num.rb | ||
hash_ident_obj.rb | ||
hash_ident_str.rb | ||
hash_ident_sym.rb | ||
hash_keys.rb | ||
hash_literal_small2.rb | ||
hash_literal_small4.rb | ||
hash_literal_small8.rb | ||
hash_long.rb | ||
hash_shift.rb | ||
hash_shift_u16.rb | ||
hash_shift_u24.rb | ||
hash_shift_u32.rb | ||
hash_small2.rb | ||
hash_small4.rb | ||
hash_small8.rb | ||
hash_to_proc.rb | ||
hash_values.rb | ||
int_quo.rb | ||
io_copy_stream_write.rb | ||
io_copy_stream_write_socket.rb | ||
io_file_create.rb | ||
io_file_read.rb | ||
io_file_write.rb | ||
io_nonblock_noex.rb | ||
io_nonblock_noex2.rb | ||
io_pipe_rw.rb | ||
io_select.rb | ||
io_select2.rb | ||
io_select3.rb | ||
io_write.rb | ||
irb_color.yml | ||
irb_exec.yml | ||
iseq_load_from_binary.yml | ||
ivar_extend.yml | ||
kernel_clone.yml | ||
kernel_float.yml | ||
kernel_tap.yml | ||
kernel_then.yml | ||
keyword_arguments.yml | ||
loop_for.rb | ||
loop_generator.rb | ||
loop_times.rb | ||
loop_whileloop.rb | ||
loop_whileloop2.rb | ||
marshal_dump_flo.rb | ||
marshal_dump_load_geniv.rb | ||
marshal_dump_load_integer.yml | ||
marshal_dump_load_time.rb | ||
masgn.yml | ||
match_gt4.rb | ||
match_small.rb | ||
method_bind_call.yml | ||
mjit_exivar.yml | ||
mjit_integer.yml | ||
mjit_kernel.yml | ||
mjit_leave.yml | ||
mjit_opt_cc_insns.yml | ||
mjit_struct_aref.yml | ||
module_eqq.yml | ||
nil_p.yml | ||
nilclass.yml | ||
num_zero_p.yml | ||
numeric_methods.yml | ||
object_allocate.yml | ||
objspace_dump_all.yml | ||
pm_array.yml | ||
ractor_const.yml | ||
ractor_float_to_s.yml | ||
range_last.yml | ||
README.md | ||
realpath.yml | ||
require.yml | ||
require_thread.yml | ||
securerandom.rb | ||
so_ackermann.rb | ||
so_array.rb | ||
so_binary_trees.rb | ||
so_concatenate.rb | ||
so_count_words.yml | ||
so_exception.rb | ||
so_fannkuch.rb | ||
so_fasta.rb | ||
so_k_nucleotide.yml | ||
so_lists.rb | ||
so_mandelbrot.rb | ||
so_matrix.rb | ||
so_meteor_contest.rb | ||
so_nbody.rb | ||
so_nested_loop.rb | ||
so_nsieve.rb | ||
so_nsieve_bits.rb | ||
so_object.rb | ||
so_partial_sums.rb | ||
so_pidigits.rb | ||
so_random.rb | ||
so_reverse_complement.yml | ||
so_sieve.rb | ||
so_spectralnorm.rb | ||
string_capitalize.yml | ||
string_casecmp.yml | ||
string_casecmp_p.yml | ||
string_concat.yml | ||
string_downcase.yml | ||
string_index.rb | ||
string_scan_re.rb | ||
string_scan_str.rb | ||
string_slice.yml | ||
string_split.yml | ||
string_swapcase.yml | ||
string_upcase.yml | ||
time_at.yml | ||
time_new.yml | ||
time_now.yml | ||
time_parse.yml | ||
time_strptime.yml | ||
time_subsec.rb | ||
vm_array.yml | ||
vm_attr_ivar.yml | ||
vm_attr_ivar_set.yml | ||
vm_backtrace.rb | ||
vm_bigarray.yml | ||
vm_bighash.yml | ||
vm_block.yml | ||
vm_block_handler.yml | ||
vm_blockparam.yml | ||
vm_blockparam_call.yml | ||
vm_blockparam_pass.yml | ||
vm_blockparam_yield.yml | ||
vm_case.yml | ||
vm_case_classes.yml | ||
vm_case_lit.yml | ||
vm_clearmethodcache.rb | ||
vm_const.yml | ||
vm_cvar.yml | ||
vm_defined_method.yml | ||
vm_dstr.yml | ||
vm_dstr_ary.rb | ||
vm_dstr_bool.rb | ||
vm_dstr_class_module.rb | ||
vm_dstr_digit.rb | ||
vm_dstr_int.rb | ||
vm_dstr_nil.rb | ||
vm_dstr_obj.rb | ||
vm_dstr_obj_def.rb | ||
vm_dstr_str.rb | ||
vm_dstr_sym.rb | ||
vm_ensure.yml | ||
vm_eval.yml | ||
vm_fiber_allocate.yml | ||
vm_fiber_count.yml | ||
vm_fiber_reuse.yml | ||
vm_fiber_reuse_gc.yml | ||
vm_fiber_switch.yml | ||
vm_float_simple.yml | ||
vm_freezestring.yml | ||
vm_gc.rb | ||
vm_gc_old_full.rb | ||
vm_gc_old_immediate.rb | ||
vm_gc_old_lazy.rb | ||
vm_gc_short_lived.yml | ||
vm_gc_short_with_complex_long.yml | ||
vm_gc_short_with_long.yml | ||
vm_gc_short_with_symbol.yml | ||
vm_gc_wb_ary.yml | ||
vm_gc_wb_ary_promoted.yml | ||
vm_gc_wb_obj.yml | ||
vm_gc_wb_obj_promoted.yml | ||
vm_iclass_super.yml | ||
vm_ivar.yml | ||
vm_ivar_embedded_obj_init.yml | ||
vm_ivar_extended_obj_init.yml | ||
vm_ivar_generic_get.yml | ||
vm_ivar_generic_set.yml | ||
vm_ivar_of_class.yml | ||
vm_ivar_of_class_set.yml | ||
vm_ivar_set.yml | ||
vm_ivar_set_on_instance.yml | ||
vm_ivar_set_subclass.yml | ||
vm_length.yml | ||
vm_lvar_init.yml | ||
vm_lvar_set.yml | ||
vm_method.yml | ||
vm_method_missing.yml | ||
vm_method_with_block.yml | ||
vm_module_ann_const_set.yml | ||
vm_module_const_set.yml | ||
vm_mutex.yml | ||
vm_neq.yml | ||
vm_newlambda.yml | ||
vm_not.yml | ||
vm_poly_method.yml | ||
vm_poly_method_ov.yml | ||
vm_poly_same_method.yml | ||
vm_poly_singleton.yml | ||
vm_proc.yml | ||
vm_raise1.yml | ||
vm_raise2.yml | ||
vm_regexp.yml | ||
vm_rescue.yml | ||
vm_send.yml | ||
vm_send_cfunc.yml | ||
vm_simplereturn.yml | ||
vm_string_literal.yml | ||
vm_struct_big_aref_hi.yml | ||
vm_struct_big_aref_lo.yml | ||
vm_struct_big_aset.yml | ||
vm_struct_big_href_hi.yml | ||
vm_struct_big_href_lo.yml | ||
vm_struct_big_hset.yml | ||
vm_struct_small_aref.yml | ||
vm_struct_small_aset.yml | ||
vm_struct_small_href.yml | ||
vm_struct_small_hset.yml | ||
vm_super.yml | ||
vm_swap.yml | ||
vm_symbol_block_pass.rb | ||
vm_thread_alive_check.yml | ||
vm_thread_close.rb | ||
vm_thread_condvar1.rb | ||
vm_thread_condvar2.rb | ||
vm_thread_create_join.rb | ||
vm_thread_mutex1.rb | ||
vm_thread_mutex2.rb | ||
vm_thread_mutex3.rb | ||
vm_thread_pass.rb | ||
vm_thread_pass_flood.rb | ||
vm_thread_pipe.rb | ||
vm_thread_queue.rb | ||
vm_thread_sized_queue.rb | ||
vm_thread_sized_queue2.rb | ||
vm_thread_sized_queue3.rb | ||
vm_thread_sized_queue4.rb | ||
vm_thread_sleep.yml | ||
vm_unif1.yml | ||
vm_yield.yml | ||
vm_zsuper.yml |
ruby/benchmark
This directory has benchmark definitions to be run with benchmark_driver.gem.
Normal usage
Execute gem install benchmark_driver
and run a command like:
# Run a benchmark script with the ruby in the $PATH
benchmark-driver benchmark/app_fib.rb
# Run benchmark scripts with multiple Ruby executables or options
benchmark-driver benchmark/*.rb -e /path/to/ruby -e '/path/to/ruby --jit'
# Or compare Ruby versions managed by rbenv
benchmark-driver benchmark/*.rb --rbenv '2.5.1;2.6.0-preview2 --jit'
# You can collect many metrics in many ways
benchmark-driver benchmark/*.rb --runner memory --output markdown
# Some are defined with YAML for complex setup or accurate measurement
benchmark-driver benchmark/*.yml
See also:
Usage: benchmark-driver [options] RUBY|YAML...
-r, --runner TYPE Specify runner type: ips, time, memory, once, block (default: ips)
-o, --output TYPE Specify output type: compare, simple, markdown, record, all (default: compare)
-e, --executables EXECS Ruby executables (e1::path1 arg1; e2::path2 arg2;...)
--rbenv VERSIONS Ruby executables in rbenv (x.x.x arg1;y.y.y arg2;...)
--repeat-count NUM Try benchmark NUM times and use the fastest result or the worst memory usage
--repeat-result TYPE Yield "best", "average" or "worst" result with --repeat-count (default: best)
--alternate Alternate executables instead of running the same executable in a row with --repeat-count
--bundler Install and use gems specified in Gemfile
--filter REGEXP Filter out benchmarks with given regexp
--run-duration SECONDS Warmup estimates loop_count to run for this duration (default: 3)
--timeout SECONDS Timeout ruby command execution with timeout(1)
-v, --verbose Verbose mode. Multiple -v options increase visilibity (max: 2)
make benchmark
Using make benchmark
, make update-benchmark-driver
automatically downloads
the supported version of benchmark_driver, and it runs benchmarks with the downloaded
benchmark_driver.
# Run all benchmarks with the ruby in the $PATH and the built ruby
make benchmark
# Or compare with specific ruby binary
make benchmark COMPARE_RUBY="/path/to/ruby --jit"
# Run vm benchmarks
make benchmark ITEM=vm
# Run some limited benchmarks in ITEM-matched files
make benchmark ITEM=vm OPTS=--filter=block
# You can specify the benchmark by an exact filename instead of using the default argument:
# ARGS = $$(find $(srcdir)/benchmark -maxdepth 1 -name '*$(ITEM)*.yml' -o -name '*$(ITEM)*.rb')
make benchmark ARGS=benchmark/erb_render.yml
# You can specify any option via $OPTS
make benchmark OPTS="--help"
# With `make benchmark`, some special runner plugins are available:
# -r peak, -r size, -r total, -r utime, -r stime, -r cutime, -r cstime
make benchmark ITEM=vm_bigarray OPTS="-r peak"