8. Why we need adaptive packaging? Day 2: Some smart engineers run YSlow and thinks… <Print css tag for feature A> <Print css tag for feature B> <Print css tag for feature C> <print HTML of feature A> <print HTML of feature B> <print HTML of feature C> … “A & B & C are always used; let’s package them together!”
9. Why we need adaptive packaging? Day 2: Awesome! <Print css tag for feature A&B&C> <print HTML of feature A> <print HTML of feature B> <print HTML of feature C> …
10. Why we need adaptive packaging? Day 3: feature C evolves… <Print css tag for feature A & B & C> <print HTML of feature A> <print HTML of feature B> If (users_signup_for_C()) { <print HTML of feature C>} …
11. Why we need adaptive packaging? Day 3: <Print css tag for feature A & B & C> <print HTML of feature A> <print HTML of feature B> If (users_signup_for_C()) { <print HTML of feature C>} … A&B are always used, while C is not. ..
12. Why we need adaptive packaging? Day 4: feature C is deprecated <Print css tag for feature A & B & C> <print HTML of feature A> <print HTML of feature B> // no one uses C { <print HTML of feature C>} …
13. Why we need adaptive packaging? Day 4: we start to send unused bits <Print css tag for feature A & B & C> <print HTML of feature A> <print HTML of feature B> // no one uses C { <print HTML of feature C>} … It is hard to remember we should remove C here.
14. Why we need adaptive packaging? One months later… <Print css tag for feature A & B & C & D & E & F & G…> if (F is used) <print HTML of feature F> <print HTML of feature G> if (F is not used) { <print HTML of feature E>} … Thousands of dead CSS rules in the package.
20. Static Resource Management Separate Declaration from actual Delivery Back to Day 1: require_static(A_css); <render HTML of feature A> require_static(B_css); <render HTML of feature B> require_static(C_css);<render HTML of feature C> <deliver all required CSS> <print all rendered HTML> Requirement Declaration lives with HTML Global Optimization on Delivery
21. Offline analysis Packager: Global JS/CSS Optimization Online process require_static(A_css); <render HTML of feature A> require_static(B_css); <render HTML of feature B> require_static(C_css); <render HTML of feature C> <deliver all required CSS> <print all rendered HTML> Usage Pattern logs Packaging algorithm “Optimal” packages
22. Packager: models Cost/Benefit tradeoff model: To package two CSS/JS files A & B: Cost: for page requests that only uses A, we waste the bytes of B (bandwidth) Benefit: for page requests that uses both A and B: we save one round trip (latency ) Maximize “Profit” (Benefit – Cost) Future: Users with different network connections have different packaging solutions Usage Pattern logs Packaging algorithm “Optimal” packages
23. Packager: models Potential extensions (and trade-offs): Consider all resources used in user browsing sessions, instead of user page loads first page slower, subsequent pages faster Consider cache probability: new files change more New user slower, old users faster Consider other costs: CSS rules JS executions HTTP header overheads Usage Pattern logs Packaging algorithm “Optimal” packages
24. Packager: algorithm A classic optimization problem: Algorithms: Greedy algorithm Simulated Annealing Clustering algorithms Trade-off between offline computation cost and accuracy: Greedy is good enough for us Usage Pattern logs Packaging algorithm “Optimal” packages
36. Human errors are unavoidable Automatic analysis is preferable: require_static(A_css); //forgot to remove the require_static require_static(B_css); <render HTML of feature B> require_static(C_css); <render HTML of feature C> <deliver all required CSS> <print all rendered HTML>
Deep integration: Each facebook home page is customized for a particular user, with features developed by many teams– some of them are applications by 3rd party developers, some of them are internal facebook feature – depending on the users’ adoption on the features and applications.Viral Adoption: we don’t know what will be the most popular Facebook feature tomorrowAgile development: our codebase change by hours, released weekly
Deep Integration: each page has many features;Viral adoption: usage pattern changes quicklyAgile development: feature changes fast
Current Assumptions: bandwidth = 1Mbps and latency = 40ms
First thing first: site speed matters.
The # of JS files are increased by 60%, the byte sites are increased by 30%. The # of pkg sent is halved, the byte size is 10% less.find | grep -v .svn | grep -v intern | grep .css$ -cfind | grep -v .svn | grep -v intern | grep .css$ | xargs cat > /tmp/dwei_2008
Developers think that timeeditor.js is a library file – in fact, it is only used in a single production page (career)On the other hand, it turns out that “resume“ function is almost always used in career page, too.
CSS is a similar story
The same trace-base analysis techniques can be use in image spriting too:
The answer is…In retrospection, this is pretty straight forward.