Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Make Ruby 2.6 Faster with JIT

Make Ruby 2.6 Faster with JIT

An introduction to MJIT in Ruby 2.6 and up. What does it do? How do you use it? How well does it work? What can go wrong?

Noah Gibbs

August 02, 2018
Tweet

More Decks by Noah Gibbs

Other Decks in Programming

Transcript

  1. Make Ruby
    2.6 Faster
    with JIT
    Noah Gibbs, AppFolio
    @codefolio / engineering.appfolio.com
    Pictures are by Arthur Rackham, and are in the Public Domain.

    View full-size slide

  2. Thank You, AppFolio!
    AppFolio pays me to write and
    speak. Thank you, AppFolio! If
    you’re looking for a Ruby job in
    Southern California, talk to us!

    View full-size slide

  3. I Often Talk Too Fast.
    If you call out “hey, slow
    down!”, I’ll try to go slower.
    And it will help your fellow audience members!

    View full-size slide

  4. JIT:
    What Is It?
    “Effortlessly Optimizing Ruby”

    View full-size slide

  5. Compiling
    Ruby interprets your
    code as it runs. C++
    (and others) compile to
    machine code before.
    “Compiling a C++ Program”

    View full-size slide

  6. JIT
    “Just-In-Time” compiling
    translates part of your
    app to fast machine
    code.
    “Running Faster Without Effort”

    View full-size slide

  7. Does JIT Work?
    TruffleRuby JIT gives 10x+
    speedup over interpreted.

    View full-size slide

  8. Does JIT Work? (2)
    Ruby 2.6 experimental
    JIT is still prerelease.
    But it gets 2.5x+ for
    the same benchmark.
    “Ruby JIT Shows Early Promise”

    View full-size slide

  9. Tradeoffs of JIT
    Nothing is perfect. JIT
    has two main
    disadvantages: memory
    usage and warmup.
    “Considering JIT’s Tradeoffs”

    View full-size slide

  10. Memory Usage (1)
    JIT tracks method calls:
    ● How many calls?
    ● How much runtime?
    ● With what argument types?

    View full-size slide

  11. Memory Usage (2)
    JIT keeps 2+ copies of
    a method and switches
    back to un-optimized if
    required.
    “De-optimizing a Method”

    View full-size slide

  12. Warmup
    JITted programs speed up as
    they compile methods. There
    is “warmup time” as new
    programs start out slower.

    View full-size slide

  13. Warmup vs Startup
    If compiling is high
    priority, early program
    speed is very slow. JVM
    is infamous for this.
    “Ruby Dancing with the JVM”

    View full-size slide

  14. Long Programs
    Servers and batch jobs
    benefit from JIT. Small
    quick programs get
    little or nothing.
    “Rake task dodging a JIT penalty”

    View full-size slide

  15. Why Didn’t
    Ruby Get
    JIT Sooner?
    “Ruby 2.5 Mocked for No JIT”

    View full-size slide

  16. JIT and Ruby Core
    JIT’s disadvantages are
    Ruby advantages -
    memory, startup. JIT
    was a tough sell.
    “Core Dev Inspects JIT Attempt”

    View full-size slide

  17. JIT and Ruby Core
    After early JIT
    prototypes looked
    good, there was a
    bake-off. MJIT won.
    “Newborn Hope for Ruby Speed”

    View full-size slide

  18. MJIT:
    Ruby’s JIT
    “MJIT In a Hurry”

    View full-size slide

  19. How Does MJIT Work?
    MJIT uses a C compiler from a
    background job with a
    Ruby-to-C translator.

    View full-size slide

  20. MJIT - the Basics (1)

    View full-size slide

  21. MJIT - the Basics (2)

    View full-size slide

  22. How MJIT Differs (1)
    Each language’s JIT
    picks the CPU priority
    for compiling. MJIT is
    conservative.
    “MJIT’s Compiler at App Start”

    View full-size slide

  23. How MJIT Differs (2)
    MJIT compiles a bit at a
    time. So it has normal
    fast Ruby startup but
    long warmup.
    “JIT’s Usual Troubles”

    View full-size slide

  24. How MJIT Differs (3)
    JVM-style JIT compiles
    in-process. That runs
    faster, but can’t easily
    shed excess memory.
    “Attempting to Free Memory”

    View full-size slide

  25. How MJIT Differs (4)
    MJIT’s background job
    lets it discard memory
    after compile. But it pays
    a compiler speed penalty.
    “Invoking the Compiler”

    View full-size slide

  26. Using JIT in Ruby 2.6
    In Ruby 2.6, you can turn JIT
    on with “--jit”. Try “ruby --help”
    to get args for JIT debugging
    and tuning.

    View full-size slide

  27. Ruby 2.6?
    With rvm, you can install
    “ruby-2.6.0-preview2”.
    Ruby-install is similar.

    View full-size slide

  28. JIT With Rails?
    Takashi’s working on
    it. But for now, it
    slows Rails down.
    “Rails, Broken on JIT”

    View full-size slide

  29. JIT Problems
    What trouble can
    JIT cause?
    “Debugging JIT Deoptimization”

    View full-size slide

  30. Want JIT Off?
    In 2.6, JIT is off by
    default. Later, you can
    disable with
    “--disable-jit”.
    “Ruby JIT, Told to Go Away”

    View full-size slide

  31. Ahead-of-Time
    AoT is compiling fully at
    app start. Can Ruby JIT
    do that?
    Not really, no.
    “Minor Problems in Ruby AoT”

    View full-size slide

  32. Questions?
    “If You Have a Question, Somebody Else Wants to Know Too”
    These slides: https://bit.ly/southeast2018-gibbs

    View full-size slide