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

Code Charcuterie

Code Charcuterie

My talk on Code Charcuterie from RailsBerry

Avatar for Aaron Patterson

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