4. JRuby is Ruby! *
1.8.7 & 1.9.3 compatibility
drop-in replacement
* see next slide
5. *caveats
• Weak but improving low-level UNIX stuff
• No C extension support
• Not maintained...off by default in 1.7
• Some features differ or unavailable
• ObjectSpace, trace funcs, callcc, fork...
10. JRuby Team
Charlie Tom
Nick Hiro Marcin Nahi Wayne Subbu Douglas Douglas
Douglas
Contribs
Douglas
Douglas Douglas
Douglas Douglas
Other
Douglas
OpenJDK Android
JVMs
30. GC Matters
• Applications grow over time
• Ruby is very object-heavy
• Multiprocess multiplies the problem
• You will eventually have issues
31. JVM GC
• Wide array of options
• Many GCs to choose from
• Scales up to massive heaps
• Best GCs in the world!
32. OpenJDK GCs
• Parallel: multi-core stop-the-world
• Concurrent: STW young, concurrent old
• G1: concurrent young and old
• Serial: single-thread STW
33. Object Homogeneity
• Everything expressed as JVM objects
• Everything shares the same infrastructure
• Including extensions, libraries, etc
• One GC to rule them all
• And one standard memory model
35. class Simple
attr_accessor :next
end
top = Simple.new
puts Benchmark.measure {
outer = 10
total = 100000
per = 100
outer.times do
total.times do
per.times { Simple.new }
s = Simple.new
top.next = s
top = s
end
end
}
57. Monitoring
• Java Management Extensions (JMX)
• Gems available for clients and servers
• jconsole and VisualVM
• Most servers provide additional tools
• New Relic, etc have JVM support
58. VisualVM
• CPU, memory, thread monitoring
• CPU and memory profiling
• VisualGC
• Heap analysis
68. @minute_hand = Path.new.tap do |mh| Draw minute hand
mh.setFill(Color::BLACK)
mh.getElements.add MoveTo.new(4, -4)
mh.getElements.add ArcTo.new(-1, -1, 0, -4, -4, false, false)
mh.getElements.add LineTo.new(0, -radius)
mh.getTransforms.add Rotate.new
end
Implement Java Event
class Refresher
include EventHandler handler
def handle(event); event.source.refresh; end
end
refresh timeline every 1s
Timeline.new.tap do |time|
time.setCycleCount Timeline::INDEFINITE
time.getKeyFrames.add(Keyframe.new(Duration.millis(1000)),
Refresher.new)
time.play
end
69. getFooBar -> fooBar
@minute_hand = Path.new.tap do |mh|
mh.setFill(Color::BLACK) was getElements
mh.elements.add MoveTo.new(4, -4)
mh.elements.add ArcTo.new(-1, -1, 0, -4, -4, false, false)
mh.elements.add LineTo.new(0, -radius)
mh.transforms.add Rotate.new
end was getTransforms
class Refresher
include EventHandler
def handle(event); event.source.refresh; end
end
Timeline.new.tap do |time|
time.setCycleCount Timeline::INDEFINITE
time.keyFrames.add(Keyframe.new(Duration.millis(1000)),
Refresher.new)
time.play
end was getKeyFrames
70. setFoo(a) -> foo = a
@minute_hand = Path.new.tap do |mh|
mh.fill = Color::BLACK was setFill
mh.elements.add MoveTo.new(4, -4)
mh.elements.add ArcTo.new(-1, -1, 0, -4, -4, false, false)
mh.elements.add LineTo.new(0, -radius)
mh.transforms.add Rotate.new
end
class Refresher
include EventHandler
def handle(event); event.source.refresh; end
end
Timeline.new.tap do |time|
was setCycleCount
time.cycleCount = Timeline::INDEFINITE
time.keyFrames.add(Keyframe.new(Duration.millis(1000)),
Refresher.new)
time.play
end
71. camelCase -> camel_case
@minute_hand = Path.new.tap do |mh|
mh.fill = Color::BLACK
mh.elements.add MoveTo.new(4, -4)
mh.elements.add ArcTo.new(-1, -1, 0, -4, -4, false, false)
mh.elements.add LineTo.new(0, -radius)
mh.transforms.add Rotate.new
end
class Refresher
include EventHandler
def handle(event); event.source.refresh; end
end
Timeline.new.tap do |time| was cycleCount
time.cycle_count = Timeline::INDEFINITE
time.key_frames.add(Keyframe.new(Duration.millis(1000)),
Refresher.new)
time.play
end was keyFrames
72. Procs as interfaces
@minute_hand = Path.new.tap do |mh|
mh.fill = Color::BLACK
mh.elements.add MoveTo.new(4, -4)
mh.elements.add ArcTo.new(-1, -1, 0, -4, -4, false, false)
mh.elements.add LineTo.new(0, -radius)
mh.transforms.add Rotate.new
end No more extra class
Timeline.new.tap do |time|
time.cycle_count = Timeline::INDEFINITE
time.key_frames.add Keyframe.new(Duration.millis(1000)) {refresh}
time.play
end
73. Common Adornments
‘add’ becomes ‘<<‘
@minute_hand = Path.new.tap do |mh|
mh.fill = Color::BLACK
mh.elements << MoveTo.new(4, -4)
mh.elements << ArcTo.new(-1, -1, 0, -4, -4, false, false)
mh.elements << LineTo.new(0, -radius)
mh.transforms << Rotate.new
end
Timeline.new.tap do |time|
time.cycle_count = Timeline::INDEFINITE
time.key_frames << Keyframe.new(Duration.millis(1000)) {refresh}
time.play
end
75. turtle("four-sided triangle") do |*args|
dim = (args[0] || 5).to_i
block_type = (args[1] || :stone).to_sym
layer do
4.times do |i|
forward dim
turnleft 90
end
end
pivot do
block :none
forward 1
turnleft 90
forward 1
turnup 90
forward 1
turndown 90
turnright 90
block block_type
end
block block_type
(1...dim).step(2).to_a.reverse.each do |i|
dim = i
layer
pivot
end
end
79. Native Extensions Suck
“Look, nobody enjoys
shooting penguins, but if
you have to shoot penguins,
well, you might as well
enjoy it.”
- Free Waterfall Sr.
80. Flowchart of Shame
Can I write it in Ruby? Script Java?
no
yes no
Does it need Can I use FFI?
to be n times
faster? no
no
Native Extension
81. Java Native Extensions
• Written in Java
• Have same performance as Java
• Use same GC as JRuby
• First Class Citizens
90. Performance
• JRuby compiles Ruby to JVM bytecode
• JVM compiles bytecode to native
• Best JIT technology in the world
• Getting even better with invokedynamic
91. How to Optimize Ruby
• Do less work
• Reduce dispatch and call overhead
• Reduce memory overhead
• Find static patterns
• Profile running code
• Emit optimized version with guards
99. InvokeDynamic
• Java 7+ feature
• Allows us to teach JVM about Ruby
• Dynamic calls can inline
• Constants become truly constant
• JVM’s best optimizations can work
117. smooth_sort
# Original Author: Keith Schwarz (htiek@cs.stanford.edu)
#
# Translated to Ruby by Chuck Remes (chuckremes on github)
#
# An implementation of Dijkstra's Smoothsort algorithm, a modification of
# heapsort that runs in O(n lg n) in the worst case, but O(n) if the data
# are already sorted. For more information about how this algorithm works
# and some of the details necessary for its proper operation, please see
#
# http://www.keithschwarz.com/smoothsort/
118. Ruby 1.8.7 Ruby 1.9.3 Ruby 2.0.0 JRuby
100000
75000
50000
25000
19590.7
11439
4750
0
Iterations per second
123. Your Turn
• Try your apps on JRuby and tell us
• Turn on JRuby in @travisci
• Let us know what you think of JRuby
• Help us make JRuby even better!
• JRuby BOF in Room C at 6:30PM