Message in a bottle

56
Message In A Bottle Konstantin Haase

Transcript of Message in a bottle

Page 1: Message in a bottle

Message In ABottle

Konstantin Haase

Page 2: Message in a bottle
Page 3: Message in a bottle
Page 4: Message in a bottle
Page 5: Message in a bottle
Page 6: Message in a bottle
Page 7: Message in a bottle
Page 8: Message in a bottle
Page 9: Message in a bottle

Ruby 1.8 is slow because it's interpreted.

Surprise! Ruby 1.9 is interpreted, too.

Page 10: Message in a bottle

Thanks!github.com / rkh / presentations

Page 11: Message in a bottle

Ruby

Page 12: Message in a bottle
Page 13: Message in a bottle
Page 14: Message in a bottle
Page 15: Message in a bottle

What We'll Look Into

MRI: method dispatch and execution

Rubinius: inline caches and JIT

JRuby: invokedynamic

Page 16: Message in a bottle
Page 17: Message in a bottle
Page 18: Message in a bottle

class DeepThought def ultimate_answer?(value) value.to_s == '42' endendDeepThought.new.ultimate_answer? 42

Page 19: Message in a bottle

They Just Love BytecodeRuby

value.to_s

MRI

getlocal valuesend :to_s, 0, nil, 0, <ic:0>

Rubinius

push_local 0send_stack :to_s, 0

JRuby

ALOAD 0LDC "to_s\uffffN\uffff\u0000\u0000\u0001\u0000\u0000\u0000\u0000\u0000\u0000...INVOKEVIRTUAL org/jruby/ast/executable/AbstractScript.initFromDescriptor (Lj......ALOAD 0INVOKEVIRTUAL ruby/__dash_e__.getCallSite0 ()Lorg/jruby/runtime/CallSite;ALOAD 1ALOAD 2ALOAD 9INVOKEVIRTUAL org/jruby/runtime/CallSite.call (Lorg/jruby/runtime/ThreadCont...

Page 20: Message in a bottle

The Plan

search for method

execute method

Page 21: Message in a bottle
Page 22: Message in a bottle

How To Speed That Up?

search faster

execute faster

Page 23: Message in a bottle

Speed Up Search

Inline Cache (aka Call/Send Site Cache)

Lookup Cache

Inlining

Page 24: Message in a bottle

Speed Up Execution

Reduce operations

Just-in-time compilation

Inlining

Speed up search

Page 25: Message in a bottle

MRI

Page 26: Message in a bottle

a method gets called

rb_call0

Page 27: Message in a bottle

static inline VALUErb_call0(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope, VALUE self){ rb_method_entry_t *me = rb_search_method_entry(recv, mid); rb_thread_t *th = GET_THREAD(); int call_status = rb_method_call_status(th, me, scope, self); // <- SEARCH if (call_status != NOEX_OK) { return method_missing(recv, mid, argc, argv, call_status); } stack_check(); return vm_call0(th, recv, mid, argc, argv, me); // <- EXECUTE}

Page 28: Message in a bottle
Page 29: Message in a bottle

/* * rb_call0 searching for a method * -> rb_method_entry * -> rb_method_entry_get_without_cache * -> search_method */static rb_method_entry_t*search_method(VALUE klass, ID id){ st_data_t body; if (!klass) { return 0; } while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) { klass = RCLASS_SUPER(klass); if (!klass) { return 0; } } return (rb_method_entry_t *)body;}

Page 30: Message in a bottle
Page 31: Message in a bottle

/* * rb_call0 executing a method * -> vm_call0 */static inline VALUEvm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_method_entry_t *me){ const rb_method_definition_t *def = me->def; VALUE val; const rb_block_t *blockptr = 0; // ... again: switch (def->type) { case VM_METHOD_TYPE_ISEQ: { rb_control_frame_t *reg_cfp; // ... vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me); val = vm_exec(th); // <- EXECUTE !!! break; } // ... } // ...}

Page 32: Message in a bottle

static VALUEvm_exec(rb_thread_t *th){ // ... go see for yourself ...}

Page 33: Message in a bottle
Page 34: Message in a bottle

DEFINE_INSNsend(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic)(...)(VALUE val)// inc += - (int)(op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));{ const rb_method_entry_t *me; VALUE recv, klass; rb_block_t *blockptr = 0; VALUE flag = op_flag; int num = caller_setup_args(th, GET_CFP(), flag, (int)op_argc, (rb_iseq_t *)blockiseq, &blockptr); ID id = op_id; /* get receiver */ recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num); klass = CLASS_OF(recv); me = vm_method_search(id, klass, ic); CALL_METHOD(num, blockptr, flag, id, me, recv);}

Page 35: Message in a bottle

Rubinius

Page 36: Message in a bottle
Page 37: Message in a bottle

klass = object.singleton_classmethod = nilwhile klass and not method method = klass.method_table.lookup(:some_method) klass = klass.direct_superclassend

Page 38: Message in a bottle

>> cm = DeepThought.method_table \?> .lookup(:ultimate_answer?).method=> #<Rubinius::CompiledMethod ultimate_answer?>>> puts cm.decode0000: push_local 0 # value0002: send_stack :to_s, 00005: push_literal "42"0007: string_dup 0008: meta_send_op_equal :==0010: ret => nil>> cm.iseq.opcodes=> #<Rubinius::Tuple: 20, 0, 49, 0, 0, 7, 1, 64, 83, 2, 11>>> cm.literals=> #<Rubinius::Tuple: :to_s, "42", :==>

Page 39: Message in a bottle

literals: :to_s, "42", :== locals: value (42)bytes: 20 0 49 0 0 7 1 64 83 2 11bytes decoded stack20 0 push_local 0 [ 42 ]49 0 0 send_stack :to_s, 0 [ "42" ]7 1 push_literal "42" [ "42", "42" ]64 string_dup [ "42", "42" ]83 2 meta_send_op_equal [ true ]11 ret [ ]

Page 40: Message in a bottle
Page 41: Message in a bottle

instruction send_stack(literal count) [ receiver +count -- value ] => send Object* recv = stack_back(count); InlineCache* cache = reinterpret_cast<InlineCache*>(literal); Arguments args(cache->name, recv, Qnil, count, stack_back_position(count)); Object* ret = cache->execute(state, call_frame, args); CHECK_AND_PUSH(ret);end

Page 42: Message in a bottle
Page 43: Message in a bottle
Page 44: Message in a bottle

Specialized Methods

cached bytecode

code with breakpoints

specialized for arguments

JITed code

Page 45: Message in a bottle
Page 46: Message in a bottle

JRuby

Page 47: Message in a bottle
Page 48: Message in a bottle

INVOKEVIRTUAL

INVOKEVIRTUAL example.getCallSite1 ...ALOAD 1ALOAD 2ALOAD 9INVOKEVIRTUAL org/jruby/runtime/CallSite.call ...

INVOKEDYNAMIC

ALOAD 1ALOAD 2ALOAD 9INVOKEDYNAMIC call ...

Page 49: Message in a bottle

INVOKEVIRTUAL

INVOKEVIRTUAL org/jruby/runtime/CallSite.call( Lorg/jruby/runtime/ThreadContext; Lorg/jruby/runtime/builtin/IRubyObject; Lorg/jruby/runtime/builtin/IRubyObject; )Lorg/jruby/runtime/builtin/IRubyObject;

INVOKEDYNAMIC

INVOKEDYNAMIC call( Lorg/jruby/runtime/ThreadContext; Lorg/jruby/runtime/builtin/IRubyObject; Lorg/jruby/runtime/builtin/IRubyObject; Ljava/lang/String; )Lorg/jruby/runtime/builtin/IRubyObject; [...]

Page 50: Message in a bottle

The Linker [org/jruby/runtime/invokedynamic/InvocationLinker .invocationBootstrap( Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String; Ljava/lang/invoke/MethodType; )Ljava/lang/invoke/CallSite;]

Page 51: Message in a bottle
Page 52: Message in a bottle

The Bootstrappublic static CallSiteinvocationBootstrap(Lookup lookup, String name, MethodType type)throws NoSuchMethodException, IllegalAccessException { CallSite site; // ... if (name.equals("call")) { site = new JRubyCallSite(lookup, type, CallType.NORMAL, false, false, true); } // ... MethodHandle myFallback = ... site.setTarget(myFallback); return site;}

Page 53: Message in a bottle
Page 54: Message in a bottle

The Fallbackpublic static IRubyObject invocationFallback(JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, String name) throws Throwable { RubyClass selfClass = pollAndGetClass(context, self); CacheEntry entry = selfClass.searchWithCache(name); if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name); } MethodHandle target = getTarget(site, selfClass, name, entry, 0); target = updateInvocationTarget(target, site, selfClass, name, entry, false, 0); return (IRubyObject)target.invokeWithArguments(context, caller, self, name);}

Page 55: Message in a bottle

imageshttp://kosmur.deviantart.com/art/assembler-79007314

https://www.facebook.com/headiushttps://www.facebook.com/koichi.sasada

https://www.facebook.com/profile.php?id=523826914�http://farm4.static.flickr.com/3207/2522976901_6ff55314cd.jpg�

http://www.flickr.com/photos/binkley27/3451700024�http://www.flickr.com/photos/funtik/1175522045�

http://en.wikipedia.org/wiki/File:Answer_to_Life.pnghttp://www.flickr.com/photos/makelessnoise/195088755/�http://www.flickr.com/photos/jeffhenshaw/4833007463/�

http://churchmusictoday.wordpress.com/2011/05/13/ten-warning-signs-for-churches-from-thom-ranier/http://www.freefoto.com/preview/28-06-3/Police-Underwater-Search-Unit

http://blog-blond.blogspot.com/2009/07/how-to-do-blogs-right.htmlhttp://fuckyouverymuch.dk/post/9661487809/we-are-ready-to-leave

http://crunchtools.com/bootstrapping-and-rooting-documentation-part-2/http://www.softmyhard.com/tag/device-instruction-manual

http://www.flickr.com/photos/quinnanya/4874581964�

Page 56: Message in a bottle

Thanks!github.com / rkh / presentations