On Jul 14, 2012, at 2:15 PM, Matt Jones wrote:

> 
> On Jul 12, 2012, at 7:44 PM, Raphael Sofaer wrote:
> 
>> Hi Matt, Vivek,
>> 
>> Here's some more information.  The app is running in production mode, 
>> although I'd like it to be a reasonable speed in dev mode also, for 
>> development.  Dev mode now is up to twice as slow.  There's tons of free 
>> memory and cpu on the machine.  Rails and hobo versions:
>>    rails (3.0.5)
>>    hobo (1.3.0)
> 
> Just to verify, which Ruby are you running on? (1.8.6 / 1.8.7 / 1.9.2)
> 
> Some preliminary profiling on 1.9.2 is turning up (bizarrely) Array#to_s as a 
> major time sink. This may be a side-effect of changes in 1.9 (it used to just 
> glue all the strings together, now it adds brackets + inspects the strings). 
> More as this develops.
> 
> --Matt Jones
> 

Replying to my own message - Array#to_s is *part* of the problem (not helped by 
debugging code I left in - ugh) but another (unexpected) time-sink is actually 
method_missing on NilClass. Turns out, this code:

a, b = nil

tries to call to_ary on nil, builds a NoMethodError, and then *silently 
discards it*. I'm seeing something like 12% of the total runtime soaking into 
this utterly useless behavior. Disabling whiny nils shifts where the time goes, 
but doesn't stop it; there's something obscure going on in Ruby's guts that's 
causing this.

In the meantime, the truly adventurous can try changing the definition of 
new_context (in template_environment.rb) from this:

    def new_context
      ctx = [ @_this, @_this_parent, @_this_field, @_this_type,
              @_form_field_path, @_form_field_paths_by_object ]
      @_this_type = nil
      res = nil
      outer_res = @view.with_output_buffer { res = yield }
      Rails.logger.error("new_context: #{caller.first}") if !outer_res.blank? 
&& outer_res.to_s != res.to_s
      @_this, @_this_parent, @_this_field, @_this_type, @_form_field_path, 
@_form_field_paths_by_object = ctx
      res.to_s
    end

to this:

    def new_context
      ctx = [ @_this, @_this_parent, @_this_field, @_this_type,
              @_form_field_path, @_form_field_paths_by_object ]
      @_this_type = nil
      res = nil
      outer_res = @view.with_output_buffer { res = yield }
      @_this, @_this_parent, @_this_field, @_this_type, @_form_field_path, 
@_form_field_paths_by_object = ctx
      if res.is_a?(Array)
        res.join('')
      else
        res.to_s
      end
    end

This restores the ruby1.8 behavior of Array#to_s, and saves a considerable 
amount of time. However, I'm not sure it's the right fix, since the return 
value of the old version of new_context was *clearly* nonsense for the cases it 
fixes (it returned a formatted array, like this: "['something', 
'some_other_thing', 'bleh']") so the join may not be needed at all, since those 
cases never turn up in the displayed HTML.

Fun fact: the ERB created by DRYML is sufficiently weird (especially with all 
the new_context recursion) that it tends to confuse ruby-prof - turning on 
memory profiling causes it to claim (sometimes) that 18014398505397860 bytes 
have been allocated...

More updates soon.

--Matt Jones

-- 
You received this message because you are subscribed to the Google Groups "Hobo 
Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/hobousers?hl=en.

Reply via email to