Skip to content

Cache type and attribute names as class variables #100

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

Merged

Conversation

timhaines
Copy link
Contributor

No description provided.

Copy link
Owner

@fotinakis fotinakis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks awesome and I think will be a huge performance boost based on our benchmarking. One comment above.

@@ -48,19 +52,22 @@ def id
# per the spec naming recommendations: http://jsonapi.org/recommendations/#naming
# For example, 'MyApp::LongCommment' will become the 'long-comments' type.
def type
object.class.name.demodulize.tableize.dasherize
class_name = object.class.name
@@class_names[class_name] ||= class_name.demodulize.tableize.dasherize
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could safely add a .freeze to the end of all of these values, here and below, which would "guarantee" the safety that this caching system will never store strings that might mutate. I can't think of a case in which they would be mutated, but to be safe.

@fotinakis
Copy link
Owner

fotinakis commented Mar 8, 2017

For posterity, here is the before profiling info where we found that the type method was super slow, particularly because of its use of ActiveSupport:

 %self      total      self      wait     child     calls  name
  9.76     10.975    10.975     0.000     0.000  1190114   String#sub!
  5.66     15.577     6.368     0.002     9.207    38162   ActiveSupport::Inflector#underscore
  5.63     83.528     6.335     0.014    77.178    51929  *Array#each
  4.12     13.607     4.634     0.006     8.966   109694   ActiveSupport::Inflector#inflections
  3.01      3.380     3.380     0.000     0.000   178845   String#to_s
  2.88     40.942     3.236     0.001    37.706    36062   ActiveSupport::Inflector#apply_inflections
  2.84      7.886     3.194     0.000     4.691   109694   <Class::ActiveSupport::Inflector::Inflections>#instance
  2.81      4.761     3.163     0.005     1.592   111144   ThreadSafe::Cache#[]

All of this expense is basically zero'd out with this PR.

@fotinakis fotinakis merged commit 5dfc662 into fotinakis:master Mar 8, 2017
@fotinakis
Copy link
Owner

This resulted in a 50-60% speed improvement in many of our API calls, especially the larger ones. 👍 🚀 🚀

fotinakis referenced this pull request in etventure/jsonapi-serializers Mar 8, 2017
@pyromaniac
Copy link

Folks, I was reviewing this part of code and realized that there are couple of issues with it:

  1. First of all, the cache grows indefinitely with any values passed, so this is a potential attack vector.
  2. Secondly, type can be fixed in a slightly different way without sacrificing the performance:
def self.type
  @type ||= ....
end

def type
  self.class.type
end

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.

3 participants