Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache Gem version checks with a variable #24

Closed
wants to merge 3 commits into from

Conversation

jcalvert
Copy link
Contributor

Cache gem version checks within a variable;

After running ruby-prof (/~https://github.com/ruby-prof/ruby-prof) on some code, I discovered there was some appreciable chunk of time in code being spent initializing Gem::Version objects and then comparing them. That lead me to this code here where I noticed these module methods were being called repeatedly.

Primarily this seems to come from entry points such as

def load_target_with_auto_include(*args)
- since load_target is being called on collections to initialize objects, the number of Gem::Version objects created and comparisons done scale directly with the number of records returned.

Since the ActiveRecord version won't be changing once an application is started, we can simply cache this value in a variable as a simple boolean and return this.

… values to avoid lots of unnecessary string comparisons
@coveralls
Copy link

Coverage Status

Coverage remained the same at 96.71% when pulling 27ef485 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

5 similar comments
@coveralls
Copy link

Coverage Status

Coverage remained the same at 96.71% when pulling 27ef485 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 96.71% when pulling 27ef485 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 96.71% when pulling 27ef485 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 96.71% when pulling 27ef485 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 96.71% when pulling 27ef485 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@dvandersluis
Copy link

FYI -- ||= won't cache if the value is false (or nil). Observe:

def method_returning_boolean
  puts "called method"  
  false  
end  

[2] pry(main)> @result ||= method_returning_boolean
called method
=> false
[3] pry(main)> @result ||= method_returning_boolean
called method
=> false
[4] pry(main)> @result ||= method_returning_boolean
called method
=> false

I believe you'll need to write it like so:

unless defined?(@mass_assignment_security_enabled)
  @mass_assignment_security_enabled = (::ActiveRecord::VERSION::MAJOR < 4 || defined?(::ActiveRecord::MassAssignmentSecurity))
end

@jcalvert
Copy link
Contributor Author

@dvandersluis You're right, it's not appropriate for a boolean. My mistake.

@jcalvert
Copy link
Contributor Author

I remember reading this sometime back - http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html

@jturkel
Copy link
Member

jturkel commented Apr 14, 2015

@jcalvert - Thanks for tracking this down!

Mutable class/module level variables are generally a source of thread-safety problems and are usually best avoided (even if it's likely innocuous in this case). Mind updating your fix to eagerly evaluate the various fields when the Goldiloader::Compatibility module is defined?

@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 1ebf793 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

4 similar comments
@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 1ebf793 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 1ebf793 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 1ebf793 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 1ebf793 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@jcalvert
Copy link
Contributor Author

@jturkel - Fair point - it would be minor but even where it would be innocuous here, you could still effectively get double call if you're say, forking before the method is called the first time because then the value is undefined in each child process.

My thought was to use constants, since these should actually, effectively be constants. And since ActiveRecord should already be loaded (via lib/goldiloader.rb) it should be safe to load preemptively like you suggest. Retrospectively there's no incentive to wait until call time to resolve the value and that eliminates the conditional.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 5db5b31 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

3 similar comments
@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 5db5b31 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 5db5b31 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.05%) to 96.76% when pulling 5db5b31 on jcalvert:cache_gem_check into 4f6054f on salsify:master.

@jturkel jturkel closed this in e7cb999 Apr 14, 2015
@jturkel
Copy link
Member

jturkel commented Apr 14, 2015

Thanks for the fix @jcalvert. I've pushed release 0.0.9 with the change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants