Shopify / measured

Encapsulate measurements and their units in Ruby and Ruby on Rails.
MIT License
337 stars 28 forks source link

Cache conversion table in JSON file to greatly speed up startup time #118

Closed kmcphillips closed 6 years ago

kmcphillips commented 6 years ago

Problem

Since #103 we have been trying to improve the startup speed of this gem. @javierhonduco has done some great work in removing some unnecessary work and making it generally start faster, but it's still slow.

Most of the time is spent in building the conversion tree. How do you find the most efficient path between any two measurements in the system. It's actually more of a graph resolution algorithm. I even tried an implementation of Dijkstra's algorithm, but ultimately it's still expensive to traverse every single one of those graphs.

When the going gets tough, cheat.

Solution

The conversion table is identical on each execution, but we still build it on each load of the environment or the gem.

This allows you to specify a cache in the system. The table is then written to a cache file, and simply loaded each time. It's on the order of 200x faster than what we already have here.

The trade offs are are that it's extra complexity, and you have to be sure the cache and the system don't get out of date. The latter is done with tests.

This implementation has one cache provider, JSON files.

When a system is updated, simply run rake cache:write to update the files in the gem and commit them to the repo.

Further details commented inline.

kmcphillips commented 6 years ago

@sharkzp Yeah I get what you're saying about the naming. Technically it's a file cache of the results of building the unit table.

It's equivalent to something like:

cache = JsonFileCache.new

measruable_class.conversion_table = cache.fetch do
  build_conversion_table_for(measurable_class)
end
kmcphillips commented 6 years ago

Thank you beautiful wonderful people for your reviews!