Skip to content

Instantly share code, notes, and snippets.

@juanpaulo
Last active August 29, 2015 14:06
Show Gist options
  • Save juanpaulo/d2b60e769a43e8e8cde0 to your computer and use it in GitHub Desktop.
Save juanpaulo/d2b60e769a43e8e8cde0 to your computer and use it in GitHub Desktop.
Barcelona Ruby Conference 2014 (Day 2)

Day 2

Types As Premature Optimization

BRIAN SHIRAI @brixen https://speakerdeck.com/brixen/types-as-premature-optimization

  • Peanut butter jelly sandwich as an example
  • Problems
    • Under-specified
    • Imperative
    • Repetitive
    • Not abstract
  • *LTR
    • Purely functional peanut butter & jelly sandwich
  • General purpose
  • We don't learn from failure
  • We learn from other's failure
  • Perception & Cognition, are they reality?
  • How to Keep Your Neighbors in Order (paper)
  • Eight fallacies of programming
    • Same scale
    • Same risk
    • Same cost (N * klocks = $)
    • Same granularity (Everything is an object, function)
    • Same abstraction (Compile at one point in time)
    • Same temporality
    • Same order (z => z^2 +c)
    • General purpose
    • nil is not null (it's an object!)
# the solution to nil class problem
class NilClass
  def method_missing(*)
    self
  end
end

# functions in ruby?
module Kernel
  ...
  module_function
end

# specify types
fun add(a: int, b: int)
  a + b
end

No [corporation] can stop an idea whose time has come. - Victor Hugo Complain about the way other people make software by making software. - ?


Writing fast Ruby

ERIK MICHAELS-OBER @sferik https://speakerdeck.com/sferik/writing-fast-ruby

In establishing engineering disciplines a 12% improvement, easily obtained, is never considered marginal, and I believe ... - Don Knuth, December, 1974 Ruby is designed to make programmers happy. - Matz

Levels of Optimization Design : Architecture and algorithms (e.g. n + 1 queries)

Source : Writing fast code

Build : Setting build flags (e.g. ./configure)

Compile : mrbc, jrubyc, rbx compile

Runtime : Thanks Matz & Koichi (e.g. RUBY_GC_MALLOC_LIMIT)

Proc#call versus yield

def slow(&block)
  block.call
end

# Over 5X faster!
def fast 
  yield
end

Block versus Symbol#to_proc

(1..100).map { |i| i.to_s }
(1..100).map(&:to_s) # 20% faster!

Enumerable#map and Array#flatten versus Enumerable#flat_map

enum.map do 
  # do something
end.flatten(1)

# Over 4.5X faster!
enum.flat_map do
  # do something
end

Hash#merge versus Hash#merge!

enum.inject({}) do |h, e|
  h.merge(e => e)
end

# Over 3X faster!
enum.inject({}) do |h, e|
  h.merge!(e => e)
end

Hash#merge! versus Hash#[]=

enum.each_with_object({}) do |e, h|
  h.merge!(e => e)
end

# Over 2X faster!
enum.each_with_object({}) do |e, h|
  h[e] = e
end

Hash#fetch versus Hash#fetch with block

{:bar => :uco}.fetch(:bar, (0..9).to_a)
{:bar => :uco}.fetch(:bar) { (0..9).to_a } # Over 2X faster!

String#gsub versus String#sub

'http://baruco.org/'.gsub('http://', 'https://')
'http://baruco.org/'.sub('http://', 'https://') # 50% faster!

String#gsub versus String#tr

'slug from title'.gsub(' ', '_')
'slug from title'.tr(' ', '_') # Over 5X faster!

Parallel vs sequential assignment

a, b = 1, 2
# 40% faster!
a = 1
b = 2

Using exceptions for control flow

begin
  bar
rescue NoMethodError
  'uco!'
end

# Over 10X faster!
if respond_to?(:bar)
  bar
else
  'uco!'
end

while loops versus Array#each_with_index

array.each_with_index do |number, index|
  # do something with number and index
end

# Over 80% faster
while index < array.size
  # do something with array[index] and index
  index += 1
end

Double pipe? Inlining? Mutability? Immutable data types in Ruby


Spelunking in Ruby

JASON R. CLARK @jasonrclark https://speakerdeck.com/jasonrclark/spelunking-in-ruby

Spelunking => Cave exploration

Built-in - put your initials in puts or prys - use custom variables $bedug

# show even swallowed exceptions
$ ruby -d deal_with_it.rb
# 
$1

Gems

# open gem
$ EDITOR=vim bundle open newrelic_rpm
# open gem
$ gem open newrelic_rpm
# restore gems
$ gem pristine newrelic_rpm

Others

# hometown
Hometown.watch(::Thread)
t = Thread.new do 
  loop {}
end
p Hometown.for(t) # returns Hometown::Trace...

# pry
@tool = "crowbar"
def crowbar
  bar_like = true
  binding.pry
end
# pry debugging ls, whereami, etc.
$ gem install pry-byebug
$ gem install pry-debugger
$ gem install pry-nav # next, step, continue, etc.

$ gem install pry-stack_explorer # up, show-stack

$ ~/.pryrc
Pry::Commands.command... # https://github.com/pry/pry/issues/607

Tools

  • jruby
  • rubinius
# sample debug
debug> break Object.my_message # supports breakpoints

# rubinius debugging
$ ruby -Xdebug rbx.rb
  • gdb
require 'thread'

puts Process.pid

m1 = Mutex.new
m2 = Mutex.new

Thread.new do 
  loop do
    ...
  end
end

t = []

t << Thread.new do
  m1.lock; sleep 1; m2.lock
end

t << Thread.new do
  m2.lock; sleep 1; m1.lock
end

t { |ts| ts.join }
puts "Done!" # deadlock! never reaches here

$ ruby deadlock.rb
2796

# use dgb
$ sudo gdb
$ attach 2796
# start debugging!
(gdb) thread apply all backtrace
# tons of logs... notice rb_mutex_lock
(gdb) call (void)rb_backtrace()
(gdb) call (void)fflush(0)

$ ~/.gdbinit
define ruby_eval
  call(rb_p(rb_eval_string_pro...
end
$ rbtrace -p <PID> --firehose
# other options
$ rbtrace -p slow=<N>
$ rbtrace -p <PID> --methods "Kernel#sleep" "Proc#call"
$ rbtrace -p <PID> --gc
$ rbtrace -p <PID> -c activerecord io

slides on http://jasonrclark.com/debug


Services, Services, Everywhere!

EVAN PHOENIX @evanphx https://speakerdeck.com/evanphx/services-services-services

  • Small things?
    • Structure an application as a composition of services
    • Isolate functionality within separate code bases
    • Profit?
  • What size is "micro"
    • "single data type"
      • User service
    • "a single operation"
      • Login service
    • "logical group"
      • Email

Benefits

  • Responsibility isolation
    • aka as "Surface Area"
    • It's the behavior of a certain app within the domain
    • As small as possible, no smaller
    • Keeps teams in control of their own destiny
  • Forced discipline
    • We're lazy. It's ok
    • We look for shortcuts and hacks, that's why we're programmers
    • Service boundaries keep us honest
    • Constraints allow for innovation, embrace them
  • Separate velocity vectors
    • Unique services have their own schedules
    • Team A doesn't need to wait on Team B to finish a feature
    • High, safe velocity == happy programmers

Pitfalls

  • Don't share ActiveRecord models between Services (SMP - Shared Model Pain)
  • Different services will want different "helpers"
  • The Breakup Redux
  • Fix "touchers"
  • Whiteboard architecture?
  • Deployment
    • N apps can't mean N deployment mechanisms
    • Each service will have differences
    • Better to use fit apps to deployment than deployment to apps
    • Unify deployment across all apps!
    • Solutions
      • Capistrano
      • PaaS
      • One configuration system
      • Use ENV vars
      • etc.
  • Do a fire drill once a month - pretend that the site is down

Inter Service Communication The Network is the Computer

Tips

  • Expect Failure
  • Tracing (logging?)
  • How & What
    • Don't argue over how X talks to Y
    • Have one convention that spans all services
    • Build tooling that exercises these conventions
    • This should eventually be second nature to everyone

How?

  • RPC
  • REST / Documents
    • JSON over HTTP from REST endpoints
      • very flexible => flexible is the productivity killer
      • standardize! don't leave room for flexibility
      • Use something like ActiveResource?
      • testing? VCR (https://github.com/vcr/vcr)
  • Message passing
    • Make communication async
    • Allows for unique communication patterns
      • Broadcast
      • Pub/Sub
    • SQS/SNS, RabbitMQ, etc.
    • testing? Abstract away our broker

Refactoring Ruby with Monads

TOM STUART @tomstuart

Monads (http://en.wikipedia.org/wiki/Monad_(functional_programming))

  • What is a stack?
    • #push (value
    • #pop
    • #top
    • #empty?
    • different implementations
  • Handling nil
    • Rails' try
    • monkey patch Object and NilClass
class Optional
  def and_then(&block) # formerly try
    if value.nil
      Optional.new(nil)
    else
      block.call(value)
    end
  end
end

Asynchronous code

GET https://api.github.com
GET https://api.github.com/orgs/ruby
GET https://api.github.com/orgs/ruby/repos
...
# Nobuyoshi Nakada

# snippet
class Eventually 
  def and_then(&block)
    Eventually.new do |success|
    ...
  end
end

Monads => abstract data type (Optional, Eventually, Many)

#and_then .from_value

https://github.com/tomstuart/monads


Go Auth Urself

MATT AIMONETTI @mattetti

  • PBKDF2
  • MessageEncryptor?

class ::Pwned
  def mashalload(*args)
    # drop table one by one
  end
  
  def marshal_dump; end

  def by
    "Eve"
  end
end

session[:pwned] = ::Pwned.new

http://godoc.org/github.com/mattetti/goRailsYourself/crypto


Smalltalk, Lisp, Bash: Three Interesting Languages

EVIL TOM STUART @rentalcustard https://docs.google.com/presentation/d/1c3N5khQkVZotZrCR4PgIIGY3FSI10VRtNC5KRlPccT0/edit#slide=id.g38d3ec8ec_0114

Smalltalk

  • Objects are classes
    • Have a class
    • Have local state
    • Have methods
  • (Polymorphic) message passing
  • Blocks
    • work like methods - can take values, take arguments
    • Have access to variables in calling context
    • ...
  • Easy to understand from 3 concepts
1 == 2
  ifTrue: [ Transcript show: "whoa" ]
  ifFalse: [ Transcript show: "ok" ]

Lisp

  • Functions
    • Accept 0..n arguments
    • Return values
    • Eschew side effects
    • Can be replaced with their result without changing meaning of program
  • Values
  • Macros
    • Look like functions
    • Operate on programs
    • Have full access to the language
    • Get expanded when used
  • Special forms
    • Have special syntax or evaluation rules
    • Look to the programmer like functions
(defn new-if
  [predicate then-clause else-clause]
  (cond predicate then-clause
	  :else else-clause)

# using special form
(defn unless
  [predicate then-clause else-clause]
  (if (not predicate) then-clause
	  :else else-clause)

# using macro
(defmacro unless
  [predicate then-clause else-clause]
  `(if (not ~predicate)
    ~then-clause
	~else-clause))

Shell

  • commands
    • Accept 0..* arguments
    • Have an exit status between 0 and 255
    • input to STDIN
    • output to STDOUT
    • errors to STDERR
  • redirection based on exit status
  • space-delimited arguments
if [ 1 -eq 2 ]
then
  echo "whoa
fi

# snippet
$ man [

What do these languages have in common?

  • Minimal
  • Pure
  • Not useful

Conclusion: Ruby uses all these concepts! What is Gyroscopic Precession?


Dancing with Robots

JULIAN CHEAL @juliancheal

artoo

guy used a dance mat to control a drone!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment