Skip to content


Rails usage of jit_stub primitives #1991

hosiawak opened this Issue · 2 comments

2 participants

Rubinius member

I thought it would be useful to know which primitives JIT doesn't know about (jit_stubs) get called fairly frequently by Rails in order to work on jitting the most frequently called ones first.

The repro is quite simple:

export RBXOPT="-X19 -Xjit.inline.debug -Xjit.log=debug.log"
./bin/rbx -S rails s

The rails app is a simple Movie CRUD db, the code is here but I think it could be any other typical rails app.

Then we generate some call frequency stats:

grep "jit_stub" debug.log  | awk '{print $(NF)}' | sort | uniq -c | sort -rn

If you find this data useful - great, if not feel free to close this issue :)

80 jit_stub_array_aset
73 jit_stub_object_kind_of
44 jit_stub_vm_object_kind_of
36 jit_stub_object_respond_to
30 jit_stub_object_hash
25 jit_stub_string_encoding
25 jit_stub_module_case_compare
19 jit_stub_string_equal
19 jit_stub_object_class
16 jit_stub_object_instance_of
16 jit_stub_bytearray_get_byte
12 jit_stub_lookuptable_store
12 jit_stub_lookuptable_has_key
11 jit_stub_object_infect
10 jit_stub_string_byte_substring
9 jit_stub_tuple_allocate
9 jit_stub_object_tainted_p
9 jit_stub_lookuptable_delete
8 jit_stub_string_append
7 jit_stub_tuple_fields
7 jit_stub_string_size
7 jit_stub_object_untrusted_p
7 jit_stub_object_id
7 jit_stub_fixnum_left_shift
6 jit_stub_regexp_options
5 jit_stub_vm_singleton_class_object
5 jit_stub_array_aref
4 jit_stub_vm_object_respond_to
4 jit_stub_thread_current
4 jit_stub_regexp_allocate
4 jit_stub_lookuptable_aref
4 jit_stub_fixnum_right_shift
3 jit_stub_tuple_dup
3 jit_stub_tuple_copy_from
3 jit_stub_string_aref
3 jit_stub_regexp_search_region
2 jit_stub_vm_reset_method_cache
2 jit_stub_vm_raise_exception
2 jit_stub_tuple_pattern
2 jit_stub_symbol_lookup
2 jit_stub_symbol_is_ivar
2 jit_stub_string_valid_encoding_p
2 jit_stub_string_transform
2 jit_stub_string_tr_expand
2 jit_stub_string_pattern
2 jit_stub_string_index
2 jit_stub_string_ascii_only_p
2 jit_stub_pointer_set_autorelease
2 jit_stub_pointer_malloc
2 jit_stub_lookuptable_allocate
2 jit_stub_fixnum_invert
2 jit_stub_compiledcode_allocate
2 jit_stub_bytearray_size
2 jit_stub_array_allocate
1 jit_stub_vm_deoptimize_inliners
1 jit_stub_symbol_to_s
1 jit_stub_symbol_is_constant
1 jit_stub_string_from_codepoint
1 jit_stub_object_taint
1 jit_stub_object_frozen_p
1 jit_stub_object_freeze
1 jit_stub_nativefunction_type_size
1 jit_stub_methodtable_store
1 jit_stub_methodtable_lookup
1 jit_stub_lookuptable_keys
1 jit_stub_io_ensure_open
1 jit_stub_included_module_allocate
1 jit_stub_encoding_compatible_p
1 jit_stub_compiledcode_dup
1 jit_stub_bytearray_set_byte
1 jit_stub_bytearray_allocate
1 jit_stub_array_new_range
1 jit_stub_array_concat

Rubinius member

@hosiawak this is great, thank you for doing some investigation! This is an area that @evanphx and I have spoken about a few times. Just calling to the jit_stub does defeat some of the optimizations that we expect the JIT to be able to do, so we do want to emit LLVM IR for some cases. There are two challenges here: 1) we need to be able to test the JIT better, 2) we want to avoid diminishing returns.

Any sophisticated JIT (any program literally) will have a tradeoff between runtime and memory. We need to ensure that we are not skewing that too badly. Also, just emitting more machine code isn't the best way to improve performance.

So, the next step is to determine higher level patterns that we want to optimize and then look at whether hand-crafting output for select jit_stub functions gets us the improvements we want.

Rubinius member

We're going to be removing the primitives, which should eliminate a lot of the jit_stub_ function calls.

@brixen brixen closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.