We were profiling our application last night with ruby-prof to find out where we could improve the speed of our api calls and found two things in jsonapi resources I think would be an easy fix to increase performance. On simpler api calls the performance was less noticeable, but in our more complex calls the performance was up to 50% faster. I wanted to put the ideas in here and see if you could think of any issues with these ideas, and if not we could create a pull request or you could if you had a better idea in mind how to facilitate these changes.
At a low level, mosts of the costs were surrounding ActiveSupport::Inflector for string names manipulation and finding class objects from strings.
The first easier fix would be to cache two methods that were called frequently and made up 25% of the performance issues in our bigger api call. I monkey patched it to test it, but these changes could be configured better to take into account cache_classes in the config and use rails cache. Only caching if we are looking for performance in staging / production.
class Resource
class << self
alias_method :resource_for_old, :resource_for
def resource_for(type)
@resources ||= {}
@resources[type] ||= resource_for_old(type)
end
end
end
class Formatter
class << self
alias_method :formatter_for_old, :formatter_for
def formatter_for(format)
@formatters ||= {}
@formatters[format] ||= formatter_for_old(format)
end
end
end
The second fix was around link generation. To test that it was faster I monkey patched these four link builder methods and returned nil.
relationships_self_link, relationships_related_link, query_link, self_link
Obviously thats not a real solution, but I wanted to test what the profiler saw. Eliminating the link generation also improved performance by 25%. Knowing that area was a performance issue, I feel that based on the parameters, a caching mechanism could created that generates the link patterns based on the parameters and then the only thing that is changed in subsequent calls is replacing the variables for the resource ids.
For example the first time the method is called, a pattern could be generated like:
https://example.com/api/v1/post/{{id}}/comments
Then on following calls the only thing to replace would be the {{id}} field and the more expensive costs of generating that initial link text could be overcome. Not all links will work for this process, but I believe most will. I need to dig deeper into the link builder generating, but those are my initial thoughts.
Some example images from the performance changes.
Our original api call

Our api after performance optimization (same calls)

We were profiling our application last night with ruby-prof to find out where we could improve the speed of our api calls and found two things in jsonapi resources I think would be an easy fix to increase performance. On simpler api calls the performance was less noticeable, but in our more complex calls the performance was up to 50% faster. I wanted to put the ideas in here and see if you could think of any issues with these ideas, and if not we could create a pull request or you could if you had a better idea in mind how to facilitate these changes.
At a low level, mosts of the costs were surrounding ActiveSupport::Inflector for string names manipulation and finding class objects from strings.
The first easier fix would be to cache two methods that were called frequently and made up 25% of the performance issues in our bigger api call. I monkey patched it to test it, but these changes could be configured better to take into account cache_classes in the config and use rails cache. Only caching if we are looking for performance in staging / production.
The second fix was around link generation. To test that it was faster I monkey patched these four link builder methods and returned nil.
relationships_self_link, relationships_related_link, query_link, self_linkObviously thats not a real solution, but I wanted to test what the profiler saw. Eliminating the link generation also improved performance by 25%. Knowing that area was a performance issue, I feel that based on the parameters, a caching mechanism could created that generates the link patterns based on the parameters and then the only thing that is changed in subsequent calls is replacing the variables for the resource ids.
For example the first time the method is called, a pattern could be generated like:
Then on following calls the only thing to replace would be the {{id}} field and the more expensive costs of generating that initial link text could be overcome. Not all links will work for this process, but I believe most will. I need to dig deeper into the link builder generating, but those are my initial thoughts.
Some example images from the performance changes.
Our original api call

Our api after performance optimization (same calls)
