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

Code Charcuterie

Code Charcuterie

My talk on Code Charcuterie from RailsBerry

Aaron Patterson

June 07, 2012
Tweet

More Decks by Aaron Patterson

Other Decks in Programming

Transcript

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

    of AT&T Intellectual Property and/or AT&T affiliated companies.
  2. -> start rendering -> start execute SQL <- finish execute

    SQL -> start execute SQL <- finish execute SQL <- finish rendering
  3. class Listener def start(event) end def finish(event) end end listener

    = Listener.new AS::Notifications.subscribe("render", listener)
  4. 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
  5. 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
  6. 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)
  7. -> 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 --
  8. 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
  9. 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
  10. = 1

  11. 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)
  12. 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)
  13. 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 } }
  14. Producer class CreatePost def initialize(q) @q = q end def

    run post = Post.new(:name => 'aaron') @q.push SavePost.new(post) end end
  15. Parallel CPU def fib n if n < 3 1

    else fib(n-1) + fib(n-2) end end 2.times.map { fib(34) }
  16. $ time ruby client.rb HELLO HELLO HELLO HELLO HELLO real

    0m2.546s user 0m0.026s sys 0m0.009s
  17. require 'socket' 5.times.map { Thread.new { sock = TCPSocket.new '127.0.0.1',

    28561 puts sock.read } }.each(&:join) Parallelize
  18. $ time ruby client.rb HELLO HELLO HELLO HELLO HELLO real

    0m0.552s user 0m0.028s sys 0m0.009s
  19. class MailSender def initialize(id) @id = id end def run

    user = User.find(@id) UserMailer.deliver_welcome_email(user) end end
  20. Attribute Access post = Post.new(:title => 'hello!') post.title # =>

    'hello!' post.respond_to?(:title) # => true
  21. Lazily Defined begin p Post.instance_method(:name) rescue NameError puts "oh no!"

    end Post.new(:name => 'aaron') p Post.instance_method(:name)
  22. 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
  23. 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
  24. 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
  25. 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
  26. 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
  27. 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???
  28. RAWWWRRRR class A def hi(stuff) end end class B <

    A def hi super(%w{ problem? }) end end
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. 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