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

Crystal & Ruby - Applying learnings from a compiled language

Crystal & Ruby - Applying learnings from a compiled language

We all enjoy the flexibility and expressiveness that languages like Ruby give us, but such flexibility is also paired with the unknown. Dealing with dynamic data and runtime conditions can lead to unknown scenarios and runtime errors.

Compiled languages, specially today offer a fresh perspective and help us developers better understand and shape our code.

This talk aims to discover certain techniques transferred from compiled languages’ realm and transfer those to dynamic languages like Ruby. Will talk from my experience working on mid-size Ruby projects (8K+ LOC).

Presented at Paris.rb Conference, June 2018

Luis Lavena

June 28, 2018
Tweet

More Decks by Luis Lavena

Other Decks in Programming

Transcript

  1. vs.

  2. OS Read source Tokenize (lexer) Build AST (parser) Codegen Execute

    Native Code (obj) Link Compilers Analyze/Infer/Optimize
  3. Crystal Language • Ruby-like syntax • Types and Inference •

    Generics • Macros • Self-hosted • LLVM-powered • Native, single-executable
  4. Crystal Language • Ruby-like syntax • Types and Inference •

    Generics • Macros • Self-hosted • LLVM-powered • Native, single-executable
  5. Types and Inference a = [1, 2, 3].map { |x|

    x + 3 } pp a # => a = [4, 5, 6] pp typeof(a) # => Array(Int32) b = [1, "a", 'b'] pp typeof(b) # => Array(String | Int32 | Char) # b << 12.5 # => Compile error (Float32)
  6. Methods and inference def add(one, two) one + two end

    add 30, 12 # Int32, Int32 => Int32 add "a", "b" # String, String => String add "a", 'b' # Compile error
  7. Methods and inference def work(worker) worker.something! end work Worker.new #

    OK work nil # Compile error (no method `something!` for `nil`)
  8. Methods & signatures def add(one : Int32, two : Int32)

    one + two end add 30, 12 # Int32, Int32 => Int32 add "a", "b" # Compile error
  9. Ruby • Types syntax will be hard to implement •

    Probably method signatures will be added in Ruby 3x3 • Type checkers possible (ie. Sorbet by Stripe) https://sorbet.run/
  10. def work(option) return option + 10 end work 5 #

    => 15 work nil # => Runtime Exception def work(option) if option return option + 10 end end work 5 # => 15 work nil # => nil Acknowledge that nil exists
  11. class Worker def work if @condition @condition.something! end end end

    class Worker def work if value = @condition value.something! end end end Accessing variables across threads
  12. $ cat example.rb a = 30 puts a + 12

    $ ruby -e 'File.binwrite("example.yarb", RubyVM::InstructionSequence.compile_file("example.rb").to_ binary)' $ ls -l total 4 -rw-r--r-- 1 luis luis 19 Jun 28 10:07 example.rb -rw-r--r-- 1 luis luis 818 Jun 28 10:07 example.yarb
  13. Bootsnap • Compiles .rb into YARB bytecode • Hooks require

    and loads instead of parsing • Optimizes lookup of $LOAD_PATH
  14. $ time gem install nokogiri-1.8.3.gem … real 5m34.507s $ gem

    compile nokogiri-1.8.3.gem … $ time gem install nokogiri-1.8.3-x86_64-linux.gem … 1 gem installed real 0m4.947s
  15. gem-compiler • RubyGems plugin (`gem compile ...`) • Pre-compile gems

    for the current platform • Plays nice with Bundler (`bundle package` and `bundle install --local`) • Reduces install time (compile nokogiri from ~5 mins to ~4 seconds) • Reduces bandwidth usage (nokogiri from ~8.8MB to ~700KB)
  16. “This PR is excellent! Event the inconsistent style and spaces

    used for your hashes, the lack of parenthesis on methods and let’s not forget the usage of tabs!” - Anonymous Ruby developer on GitHub
  17. Formatting code • Reduces bikeshedding • Consistent readability following official

    styleguides • Improves contribution • Broad implementation and success on other languages: Golang, Rust, Elixir • Proactive vs. Passive
  18. $ cat example.rb def hello name puts "Hello #{name}!!!" end

    $ rufo example.rb $ cat example.rb def hello(name) puts "Hello #{name}!!!" end rufo: Ruby formatter
  19. Optimization resources • Load time: Bootsnap http://github.com/Shopify/bootsnap • Pre-compiled extensions:

    gem-compiler https://github.com/luislavena/gem-compiler • Code formatting: rufo https://github.com/ruby-formatter/rufo