Patterns and Performance of InvokeDynamic in JRuby
Japan JRuby User Group
Hiroshi Nakamura
@nahi nahi@ruby-lang.org
This slides: http://bit.ly/jjug-indy-jruby-en
Code: http://bit.ly/jjug-indy-jruby-code
Self introduction
Custom system development around network security: C/C++ (18 years), Java (13 years), Ruby (13 years)
OSS development at free-time: CRuby (8 years), JRuby (2 years), soap4r, httpclient, etc.
What's JRuby - http://jruby.org/
1.6.6 is the latest (1.6.7 coming soon)
Ruby runs atop JVM: Dynamic typed language
Open Source (CPL, GPL, LGPL)
Started 10 years ago
5 years from full-time developer
Goal of this talk
Showing InvokeDynamic usages on JRuby
What I want to tell you today;
Revisit InvokeDynamic features
Link a caller (invokedynamic) with method (MH) at runtime
Common optimization with Java for dynamic typed languages
Patterns of InvokeDynamic
MH juggling in JRuby
InvokeDynamic optimization recipe
Signature example;
2 params of Object and long, returns Object
→(Object self, long value)Object
InvokeDynamic Patterns in JRuby
1. String literal
2. Other literals
3. Quasi-constant
4. Instance variable
5. Method invocation
6. Math operation
1. String literal
Where to apply: String literals
message = "Hello"�message << name << "!"
Call signature: (ThreadContext ctx)Object
&jrNewString(ctx, str): target
&insert(str = "Hello"):insert 1 arg
combine
ThreadContext is for the Object containing runtime environment. All operations needs it.
2. Other literals
Where to apply: Immutable literals
times = 10000�matcher = /[A-Z][a-z]*/
Call signature: (ThreadContext ctx)Object
&constant[10000]: MH returns const
&drop(ctx): drop 1 arg
3. Quasi-constant
Where to apply: Constant reference in Ruby
&thisMethod(ctx): re-link this MH to update value
&constant[obj]: MH for current value as const
&drop(ctx): drop 1 arg
&SwitchPoint(&,&): invalidated if any const is defined
DEFAULT = Container.new.freeze�comtainer = DEFAULT�DEFAULT = nil
Call signature: (ThreadContext ctx)Object
4. Instance variable
Where to apply: Instance variable access
module Cache� def cache(value)� @cache = value� end�end�class Foo� include Cache�end�class Bar� include Cache�end
4. Instance variable (contd.)
&jrGetVariable(obj, index): target
&thisMethod(self): re-link this MH to update self
Call signature: (Object self)Object
&insert(obj = self, index = 2): insert
&filterRetval(&nullToNil): combine retval filter
&jrTestClass(self): check if class is the same
&GuardWithTest(&,&,&): invalidate if class is different
5. Method invo-� cation
Where to apply: Any method invocation
$name = [:JRuby, "Ruby", 42]�def process(router)� router.say_hello($names.sample)�end
Call signature:
(ctx, self)Object
(ctx, self, arg1)Object
(ctx, self, arg1, arg2)Object
(ctx, self, arg1, arg2, arg3)Object
(ctx, self, arg[])Object
5. Method invocation (contd.)
&jrTestClass(self): check the class
&drop(ctx, self): drop 2 args
&GuardWithTest: invalidate if class is different
&SwitchPoint: invalidated if a method added to class
Call signature: (ctx, self, arg1)Object
&jrTarget(ctx, self, arg1): target
&thisMethod(ctx, self, arg1): re-link
&thisMethod(ctx, self, arg1): re-link
6. Math operation
Where to apply: arithmetic op for int or float as RHS
fib(n - 2) + fib(n - 1)�display if (x >= 5)�elapsed = msec * 1000.0
Call signature: (ctx, self)Object
&jrInvoke(ctx, self, value): common call
&jrTestClass(self): is LHS an Integer
&jrFixnumMinusTwo(ctx, self): shortcut
&drop(ctx): drop 1 arg
&GuardWithTest: shortcut if LHS is an Integer
InvokeDynamic Performance in JRuby
Hooray JVM!
Micro benchmark
String literal
Other literals
Quasi-const
Instance variable
Method invocation
Math operation
All
- Java 7 w/o indy == 1. Higher is faster.
- Measured loop of single line for each pattern.
- "All" contains cascading invocation of all.
Binary-tree benchmark
AVL tree (recursive)
Red-black tree (loop)
- Java 7 w/o indy == 1. Higher is faster.
Conclusion
Fast (if you use this right)
Complex (I could not master it yet)
Optimization is easier than doing it by language runtime -> Let JVM do it
Other application scopes?