BetterErrors / better_errors

Better error page for Rack apps
MIT License
6.87k stars 436 forks source link

Rails boots very slowly with Ruby 2.0.0 and bindings_of_caller #124

Closed csmuc closed 11 years ago

csmuc commented 11 years ago

=> Rails boots very slowly:

With binding_of_caller: time rails runner "puts 'hi'" hi

real 0m15.633s user 0m14.182s sys 0m1.054s

Without: time rails runner "puts 'hi'" hi

real 0m6.225s user 0m4.951s sys 0m0.997s

Workaround: Add "Thread.current[:__better_errors_exception_lock] = true" and "Thread.current[:__better_errors_exception_lock] = false" to beginning and end of config/environment.rb

I think config/environment.rb is specific to Rails, so there should be some kind of generic fix for Rack apps. Maybe the Rack API provides something useful in that regard..

allenwyma commented 11 years ago

Add it to the environment? Sounds a bit dangerous, shouldnt' this be added to development.rb? And also shouldn't we check to make sure that BetterErrors is defined? Also, if this has to do with binding_of_caller, then why do you need to lock and unlock on the better_errors?

csmuc commented 11 years ago

Dangerous? I don't think setting a thread-local variable could that be much of a problem. But yes, that's only a dirty quick-fix to get the boot time back to normal again.

I don't think development.rb would help much because at that time Rails already has booted (and raised lots of LoadErrors on its way).

allenwyma commented 11 years ago

Oh okay, this is independent of better errors? I just want to make sure if I do decide to add this in, that it doesn't mess up my production code.

csmuc commented 11 years ago

This code doesn't depend on better_errors. It simply sets the thread-local variable with the name "__better_errors_exception_lock".

Also try running some specs, the better_errors gem is typically not available in test (see your Gemfile).

banister commented 11 years ago

I call to_a on the InstructionSequence object to grab the frame description, if to_a is lazy (which it likely is) this is the source of the slow down. I can probably figure out another way to get frame description, or send a pull request upstream to expose that at the C level which would be much faster.

banister commented 11 years ago

@csmuc i've pushed a pre gem for binding_of_caller that avoid the expensive InstructionSequence#to_a operation when generating bindings. Can you please try this and let me know whether it speeds things up?

allenwyma commented 11 years ago

@banister much better! Thanks! STill seems a bit slow, but I may just have that feeling stuck in my head from before. Can anyone else confirm?

csmuc commented 11 years ago

I only see a slight speed up, time rake environment:

without binding_of_caller: real 0m5.349s user 0m4.283s sys 0m0.961s

0.6.9 with my workaround: real 0m5.499s user 0m4.458s sys 0m0.962s

0.6.9 without workaround: real 0m19.195s user 0m17.976s sys 0m1.052s

6beaffd345 without workaround: real 0m17.598s user 0m16.364s sys 0m1.021s

banister commented 11 years ago

Ok, i'll try one more strategy. I think the set of call-stack bindings is rebuilt every time i open the debug inspector, so i'll try doing all the binding gathering inside the debug inspector block itself

banister commented 11 years ago

@csmuc ok i pushed a new pre gem with this fix, tell me if that improves things

csmuc commented 11 years ago

yep, with cb6a821ab6: real 0m5.746s user 0m4.687s sys 0m0.983s

Almost as fast as without using the gem! Thanks!

banister commented 11 years ago

I pushed a new binding_of_caller with this fix applied, version 0.7 :)