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

Sprockets 4 performance regressions #413

Closed
TylerHorth opened this issue Oct 31, 2016 · 3 comments
Closed

Sprockets 4 performance regressions #413

TylerHorth opened this issue Oct 31, 2016 · 3 comments

Comments

@TylerHorth
Copy link

TylerHorth commented Oct 31, 2016

This is a general issue to track performance regressions from sprockets 3 to sprockets 4.

Overview

Sprockets 4 is presently several times slower than its predecessor. Shopify saw compile time go from 1m to 7m, and page load time go from 600ms to 5000ms. This will need to be addressed before we can expect wide scale adoption.

Cause

This regression seems to be in large part due to source map generation. Hacking away source map logic returns Shopify's compile and page load times back to pre-sprockets4 levels.

Solution

The problem can be divided into two main tasks: computing the source map itself, and storing the source map after processing.

Generation

Individual processors are responsible for generating their own source maps. Unfortunately, this takes time: generating source maps without storing them saw Shopify's compile time reach ~3m. Presently, source maps are generated by default, and there is no simple way of disabling them.

One solution is to extract source map generation out of the default pipeline.

Storage

Storing source maps is a challenge on its own simply due to the sheer size of them. Source maps in their raw form can take up to 10 times the space of the original files. The source map v2 and v3 specs made strides on improving this by storing the mappings in a compressed form. Presently however, sprockets decodes and stores source maps in their raw form. This is a problem since digesting and caching these immense files takes a lot of space and time.

I have got a WIP solution in #402. This initial implementation sees compile time reduced to 3m50s from the original 7m10s by storing maps in their compressed form according to the source map v3 spec. This also resolves the page load slowdown which was a result of running out of memory.


I'll try to keep this issue up to date as progress is made. Please, if you know of any other areas sprockets has regressed, leave a comment here or link to the relevant issue.

cc @bouk

@TylerHorth
Copy link
Author

Just a quick update on this:

Compressed source maps PR (#402) has been merged, which removed most of the Sprockets overhead for storing source maps.

The remaining time was mostly spent in the compilation step, particularly compiling coffee-script source maps. Disabling source-maps just for coffee-script brings compile time down from 220s to around 80s. Initially I had thought this problem was innate to the CoffeeScript compiler and thus unsolvable, but further testing revealed that the CoffeeScript compiler is able to compile source maps at virtually no extra cost. The problem seems to lie specifically with the coffee-script gem. I have opened an issue on the ruby-coffee-script repo with more details.

@schneems
Copy link
Member

@TylerHorth you're awesome, thanks! I also think being able to turn on and off the valid_processor_metadata_value? could be a nice perf bump #383 we are already essentially doing that same check when we run a processor result through the digest_utils#digest method, so I don't think we need to duplicate all that work.

@schneems
Copy link
Member

Thanks for the PRs. I'm going to close this in favor of #410 which is specific to not generating source maps. I think we need that ability. Happy to look at any additional perf issues that may come up.

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

No branches or pull requests

2 participants