Code Charcuterie

Code Charcuterie

My talk on Code Charcuterie from RailsBerry

F29327647a9cff5c69618bae420792ea?s=128

Aaron Patterson

June 07, 2012
Tweet

Transcript

  1. 2.
  2. 11.

    AT&T, AT&T logo and all AT&T related marks are trademarks

    of AT&T Intellectual Property and/or AT&T affiliated companies.
  3. 14.
  4. 15.
  5. 16.
  6. 17.
  7. 18.
  8. 19.
  9. 20.
  10. 21.
  11. 22.
  12. 23.
  13. 25.
  14. 26.
  15. 27.
  16. 28.
  17. 31.
  18. 32.
  19. 33.
  20. 34.
  21. 37.
  22. 46.
  23. 51.

    -> start rendering -> start execute SQL <- finish execute

    SQL -> start execute SQL <- finish execute SQL <- finish rendering
  24. 53.

    class Listener def start(event) end def finish(event) end end listener

    = Listener.new AS::Notifications.subscribe("render", listener)
  25. 55.

    Make it Quack class Timed def initialize(pattern, delegate) @delegate =

    delegate @timestack = Hash.new { |h,id| h[id] = Hash.new { |ids,name| ids[name] = [] } } end def start(name, id, payload) @timestack[id][name].push Time.now end def finish(name, id, payload) started = @timestack[id][name].pop @delegate.call(name, started, Time.now, id, payload) end end
  26. 56.

    Tiny Factory def subscribe(pattern = nil, listener = Proc.new) if

    listener.respond_to?(:call) subscriber = Timed.new pattern, listener else subscriber = listener end @subscribers << subscriber end
  27. 58.

    class Indented def initialize @indentation = 0 end def start

    name, id, payload print indent puts "-> #{name} -- #{payload[:virtual_path]}" @indentation += 1 end def finish name, id, payload @indentation -= 1 print indent puts "<- #{name} -- #{payload[:virtual_path]}" end private def indent " " * @indentation end end ActiveSupport::Notifications.notifier.subscribe(nil, Indented.new)
  28. 59.

    -> process_action.action_controller -- -> render_template.action_view -- -> !render_template.action_view -- sessions/index

    <- !render_template.action_view -- sessions/index <- render_template.action_view -- -> !render_template.action_view -- layouts/application -> render_partial.action_view -- -> !render_template.action_view -- layouts/_navigation <- !render_template.action_view -- layouts/_navigation <- render_partial.action_view -- -> render_partial.action_view -- -> !render_template.action_view -- sessions/_slim_login <- !render_template.action_view -- sessions/_slim_login <- render_partial.action_view -- <- !render_template.action_view -- layouts/application <- process_action.action_controller --
  29. 60.
  30. 61.

    ml !render_template.action_view (4.564 ms) virtual_path layouts/application render_partial.action_view (0.346 ms) identifier

    /app/views/layouts/_navigation render_partial.action_view (0.133 ms) identifier /app/views/sessions/_logout.ht !render_template.action_view (0.291 ms) virtual_path layouts/_navigation !render_template.action_view (0.087 ms) virtual_path sessions/_logout _l
  31. 62.

    tion_controller (0.021 ms) MessagesController index GET /messages process_action.action_controller (95.463 ms)

    controller MessagesController action index method GET path /messages sql.active_record (5.671 ms) sql SELECT "messages"."id" AS t0_r0, "messages"."address_id" AS t0_r1, "messages"."from" AS t0_r2, "messages"."to" AS t0_r3, "messages"."disposable" AS t0_r4, "messages"."subject" AS t0_r5, "messages"."body" AS t0_r6, "messages"."plain" AS t0_r7, "messages"."html" AS t0_r8, "messages"."created_at" AS t0_r9, "messages"."updated_at" AS t0_r10, "messages"."parsed_message_id" AS t0_r11, "addresses"."id" AS t1_r0, "addresses"."name" AS t1_r1, "addresses"."person_id" AS t1_r2, "addresses"."created_at" AS t1_r3, "addresses"."updated_at" AS t1_r4 FROM "messages" LEFT render_template.action_view (63.632 ms) identifier /app/views/messages/index.html layout layouts/application
  32. 65.
  33. 67.
  34. 68.

    = 1

  35. 71.
  36. 72.
  37. 75.

    class Sleeper def run; sleep(1); end end q = Queue.new

    10.times { q.push Sleeper.new } 10.times { q.push nil } # 10 cores! wow! 10.times.map { Thread.new { while obj = q.pop obj.run end } }.each(&:join)
  38. 77.

    class Sleeper def run; sleep(1); end end q = SlowQueue.new

    # make `pop` cost more 10.times { q.push Sleeper.new } 10.times { q.push nil } # 10 cores! wow! 10.times.map { Thread.new { while obj = q.pop obj.run end } }.each(&:join)
  39. 82.
  40. 83.
  41. 84.
  42. 92.
  43. 93.

    Splitting Work cpu_queue = Queue.new io_queue = Queue.new 5.times {

    Thread.new { io_queue.pop.run } } 10.times { Thread.new { cpu_queue.pop.run } }
  44. 95.

    Producer class CreatePost def initialize(q) @q = q end def

    run post = Post.new(:name => 'aaron') @q.push SavePost.new(post) end end
  45. 96.
  46. 97.

    Parallel CPU def fib n if n < 3 1

    else fib(n-1) + fib(n-2) end end 2.times.map { fib(34) }
  47. 100.
  48. 103.

    $ time ruby client.rb HELLO HELLO HELLO HELLO HELLO real

    0m2.546s user 0m0.026s sys 0m0.009s
  49. 104.

    require 'socket' 5.times.map { Thread.new { sock = TCPSocket.new '127.0.0.1',

    28561 puts sock.read } }.each(&:join) Parallelize
  50. 105.

    $ time ruby client.rb HELLO HELLO HELLO HELLO HELLO real

    0m0.552s user 0m0.028s sys 0m0.009s
  51. 110.

    class MailSender def initialize(id) @id = id end def run

    user = User.find(@id) UserMailer.deliver_welcome_email(user) end end
  52. 113.
  53. 118.

    Attribute Access post = Post.new(:title => 'hello!') post.title # =>

    'hello!' post.respond_to?(:title) # => true
  54. 119.

    Lazily Defined begin p Post.instance_method(:name) rescue NameError puts "oh no!"

    end Post.new(:name => 'aaron') p Post.instance_method(:name)
  55. 121.

    Definition Time def method_missing(method, *args, &block) unless self.class.attribute_methods_generated? self.class.define_attribute_methods ...

    end end def respond_to?(name, include_private = false) unless self.class.attribute_methods_generated? self.class.define_attribute_methods end super end
  56. 122.

    Who called respond_to? {:method=>"name="} ########################################################################################## lib/active_record/attribute_assignment.rb:81:in `block in assign_attributes' lib/active_record/attribute_assignment.rb:78:in

    `each' lib/active_record/attribute_assignment.rb:78:in `assign_attributes' lib/active_record/base.rb:498:in `initialize' test/cases/argh.rb:16:in `new' test/cases/argh.rb:16:in `<main>' ########################################################################################## {:method=>"_run__1290908416815974468__initialize__2045902499019596289__callbacks"} ########################################################################################## lib/active_support/callbacks.rb:398:in `__run_callback' lib/active_support/callbacks.rb:385:in `_run_initialize_callbacks' lib/active_support/callbacks.rb:81:in `run_callbacks' lib/active_record/base.rb:501:in `initialize' test/cases/argh.rb:16:in `new' test/cases/argh.rb:16:in `<main>' ########################################################################################## Number of Doubts
  57. 124.

    use super class Subject < ActiveRecord::Base def initialize(*args) super set_email_address

    # after_init end protected def set_email_address ... end end Number of Doubts
  58. 126.

    What method? {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"}

    {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} {:method=>"name="} {:method=>"_run__1048083580144971540__initialize__3082064574212577540__callbacks"} Number of Doubts
  59. 127.

    Define Methods def define_attribute_methods .... @attribute_methods_mutex.synchronize do return if attribute_methods_generated?

    superclass.define_attribute_methods unless self == base_class super(column_names) column_names.each { |name| define_external_attribute_method(name) } @attribute_methods_generated = true end end
  60. 128.

    Define Methods def define_attribute_methods .... @attribute_methods_mutex.synchronize do return if attribute_methods_generated?

    superclass.define_attribute_methods unless self == base_class super(column_names) column_names.each { |name| define_external_attribute_method(name) } @attribute_methods_generated = true end end wtf???
  61. 129.

    RAWWWRRRR class A def hi(stuff) end end class B <

    A def hi super(%w{ problem? }) end end
  62. 137.

    define_attribute_method def define_attribute_method(attr_name) ... unless instance_method_already_implemented?(method_name) generate_method = "define_method_#{matcher.method_missing_target}" if

    respond_to?(generate_method, true) send(generate_method, attr_name) else define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s end end end
  63. 138.

    define_attribute_method def define_attribute_method(attr_name) ... unless instance_method_already_implemented?(method_name) generate_method = "define_method_#{matcher.method_missing_target}" if

    respond_to?(generate_method, true) send(generate_method, attr_name) else define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s end end end
  64. 139.

    define_attribute_method def define_attribute_method(attr_name) ... unless instance_method_already_implemented?(method_name) generate_method = "define_method_#{matcher.method_missing_target}" if

    respond_to?(generate_method, true) send(generate_method, attr_name) else define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s end end end
  65. 140.

    define_attribute_method def define_attribute_method(attr_name) ... unless instance_method_already_implemented?(method_name) generate_method = "define_method_#{matcher.method_missing_target}" if

    respond_to?(generate_method, true) send(generate_method, attr_name) else define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s end end end
  66. 141.

    define_attribute_method def define_attribute_method(attr_name) ... unless instance_method_already_implemented?(method_name) generate_method = "define_method_#{matcher.method_missing_target}" if

    respond_to?(generate_method, true) send(generate_method, attr_name) else define_optimized_call generated_attribute_methods, method_name, matcher.method_missing_target, attr_name.to_s end end end
  67. 143.

    define_method_attribute define_method_attribute= define_method_attribute_before_type_cast define_method_attribute? define_method_attribute_changed? define_method_attribute_change define_method_attribute_will_change! define_method_attribute_was define_method_reset_attribute! define_method__attribute

    define_method_attribute define_method_attribute= define_method_attribute_before_type_cast define_method_attribute? define_method_attribute_changed? define_method_attribute_change define_method_attribute_will_change! define_method_attribute_was define_method_reset_attribute! define_method__attribute
  68. 144.

    define_method_attribute define_method_attribute= define_method_attribute_before_type_cast define_method_attribute? define_method_attribute_changed? define_method_attribute_change define_method_attribute_will_change! define_method_attribute_was define_method_reset_attribute! define_method__attribute

    define_method_attribute define_method_attribute= define_method_attribute_before_type_cast define_method_attribute? define_method_attribute_changed? define_method_attribute_change define_method_attribute_will_change! define_method_attribute_was define_method_reset_attribute! define_method__attribute
  69. 145.

    define_method_attribute define_method_attribute= define_method_attribute_before_type_cast define_method_attribute? define_method_attribute_changed? define_method_attribute_change define_method_attribute_will_change! define_method_attribute_was define_method_reset_attribute! define_method__attribute

    define_method_attribute define_method_attribute= define_method_attribute_before_type_cast define_method_attribute? define_method_attribute_changed? define_method_attribute_change define_method_attribute_will_change! define_method_attribute_was define_method_reset_attribute! define_method__attribute
  70. 146.

    define_method_attribute define_method_attribute= define_method_attribute_before_type_cast define_method_attribute? define_method_attribute_changed? define_method_attribute_change define_method_attribute_will_change! define_method_attribute_was define_method_reset_attribute! define_method__attribute

    define_method_attribute define_method_attribute= define_method_attribute_before_type_cast define_method_attribute? define_method_attribute_changed? define_method_attribute_change define_method_attribute_will_change! define_method_attribute_was define_method_reset_attribute! define_method__attribute THANKS ACTIVE MODEL
  71. 153.

    def define_method_attribute(attr_name) generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 def __temp__

    #{internal_attribute_access_code(attr_name, attribute_cast_code(attr_name))} end alias_method '#{attr_name}', :__temp__ undef_method :__temp__ STR end
  72. 158.

    Post#created_at def created_at attr_name = 'created_at' unless @attributes.has_key?(attr_name) @attributes_cache[attr_name] ||=

    (missing_attribute(attr_name, caller) end (v=@attributes[attr_name]) && ActiveRecord::ConnectionAdapters::SQLiteColumn.string_to_time(v)) end
  73. 159.

    Post#created_at def created_at attr_name = 'created_at' unless @attributes.has_key?(attr_name) @attributes_cache[attr_name] ||=

    (missing_attribute(attr_name, caller) end (v=@attributes[attr_name]) && ActiveRecord::ConnectionAdapters::SQLiteColumn.string_to_time(v)) end DOUBTS INCREASING
  74. 161.

    type_cast_code def type_cast_code(var_name) klass = self.class.name case type when :string,

    :text then var_name when :integer then "(#{var_name}.to_i rescue #{var_name} ? 1 : 0)" when :float then "#{var_name}.to_f" when :decimal then "#{klass}.value_to_decimal(#{var_name})" when :datetime, :timestamp then "#{klass}.string_to_time(#{var_name})" when :time then "#{klass}.string_to_dummy_time(#{var_name})" when :date then "#{klass}.string_to_date(#{var_name})" when :binary then "#{klass}.binary_to_string(#{var_name})" when :boolean then "#{klass}.value_to_boolean(#{var_name})" else var_name end end
  75. 162.

    type_cast def type_cast(value) return nil if value.nil? return coder.load(value) if

    encoded? klass = self.class case type when :string, :text then value when :integer then value.to_i rescue value ? 1 : 0 when :float then value.to_f when :decimal then klass.value_to_decimal(value) when :datetime, :timestamp then klass.string_to_time(value) when :time then klass.string_to_dummy_time(value) when :date then klass.string_to_date(value) when :binary then klass.binary_to_string(value) when :boolean then klass.value_to_boolean(value) else value end end
  76. 165.
  77. 166.
  78. 168.

    def read_attribute(attr_name) # If it's cached, just return it @attributes_cache.fetch(attr_name.to_s)

    { |name| column = @columns_hash[name] value = @attributes.fetch(name) { return attribute_missing(name, caller) } # Cache if we're supposed to if self.class.cache_attribute?(name) @attributes_cache[name] = column.type_cast(value) else column.type_cast value end } end
  79. 172.
  80. 173.