500 likes | 641 Views
Adaptive Static Resource Optimization. David Wei and Changhao Jiang. The AJAX Experience 2009 Sep 15, 2009 Boston, MA. Best practice: from theory to operation?. “Reduce # of HTTP Requests”. Package JS/CSS; Sprite Image. Best practice: from theory to operation?. “Reduce # of HTTP Requests”.
E N D
Adaptive Static Resource Optimization David Wei and ChanghaoJiang The AJAX Experience 2009 Sep 15, 2009 Boston, MA
Best practice: from theory to operation? “Reduce # of HTTP Requests” Package JS/CSS; Sprite Image
Best practice: from theory to operation? “Reduce # of HTTP Requests” Package JS/CSS; Sprite Image Interface & Infrastructure Operation
Facebook’s day-to-day challenges • Deep Integration • Viral Adoption • Agile Development • Performance optimization has to be adaptive!
Perf optimization must be adaptive • Day 1: Some smart engineers start a project! <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> … “Let’s write a new page with features A, B and C!”
Day 2: Some smart engineers run YSlow and says… <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!”
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> …
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>} …
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. ..
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>} …
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.
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.
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>} … Performance optimization has to be adaptive! Thousands of dead CSS rules in the package.
Adaptive Static Resource Optimization Challenges: • Deep Integration • Viral Adoption • Agile Development Responses: • Build interface to separate requirement declaration and delivery of static resources • Requirement declaration: lives with HTML generation, logged • Delivery: Globally optimized by analyzing the logged trace
Interfaces • 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> Separate Declaration from actual Delivery Requirement Declaration lives with HTML Global Optimization on Delivery
Packager: Global JS/CSS Optimization Offline analysis 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
Packager: Usage Pattern Logs Usage Pattern logs
Packager: Cost/Benefit Model • To package two files A & B: • “Cost”: for page requests that only uses A, we waste the bytes of B, vice versa • “Benefit”: for page requests that uses both A and B: we save one round trip • Bytes / Bandwidth ~ Latency • “Profit” to be maximized: Benefit – Cost
Packager: Cost/Benefit Model • Assume: latency = 40ms, and bandwidth = 1 Mbps • A+B: 40ms * 11.131M • No cost, pure gain. • Definitely package
Packager: Cost/Benefit Model • Assume: latency = 40ms, and bandwidth = 1 Mbps • B+C: 40ms * 11.1M • – 300B / 1Mbps * 0.031M • Benefit larger than cost • OK to package
Packager: Cost/Benefit Model • Assume: latency = 40ms, and bandwidth = 1 Mbps • B+D: 40ms * 1K • – 2K / 1Mbps * 11.13M • Cost larger than benefit • Don’t package
Packager: Algorithms • Greedy algorithm • Simulated Annealing • Clustering algorithms • … Packaging algorithm
Packager: Optimal packages • Pkg 1: A, B, C • Pkg 2: E, F, G Usage Pattern logs Packaging algorithm “Optimal” packages
Adaptive Static Resource Optimization Adaptive Packaging / Spriting • Cross-feature optimizations (e.g. search + ads) • Adaptive to change of user behaviors and code developments • Same methodology works for image spriting
Adaptive Static Resource Optimization Adaptive progressive rendering • flush the commonly used JS/CSS/Images to the browsers, before the page is generated at the server • Browser downloads JS/CSS in parallel with page generation at server side
Adaptive Progressive Rendering Adaptive progressive rendering • Progressive rendering: flush the commonly used JS/CSS/Images to the browsers, before the page is generated at the server
Adaptive progressive rendering What are the common JS / CSS should we flush? Usage Pattern logs
Adaptive progressive rendering Sum on the page name:
Adaptive progressive rendering Remove the rare usages
Adaptive Static Resource Optimization Adaptive progressive rendering • More than 500 msec gain for home page end-to-end time • Adaptive to the change of popular resources • Need to solve issues with redirections, HTTP-only cookie and buffers
Update frequency • Too slow: fail to adapt to usage changes • Too fast: invalidate caches • Usually weekly • Can be smarter
Resources for new features • No usage logs available • Developers to estimate the initial usage pattern • Update packages one day after release, if necessary
Deployment status since Nov 2008 • Rebalance weekly based on previous week’s usage pattern (>100K unique usage patterns) • Javascript and CSS packaging only (image soon)
Scalable with development JS/CSS Code base: Nov 2008 -> Sep 2009
Adaptive to new usages # of JS/CSS Packages served in the past month
Experiment: Adaptive Image Spriting The puzzle of image spriting: • Thousands of virtual gifts with static images, which to sprite?
Experiment: Adaptive Image Spriting The puzzle of image spriting: • The answer is…
Regression detection can be trickier “The page has 5KB more Javascripts!” • Regression introduced by Packager? • Or, by the code?
“All models are wrong. Some models are useful.” • Not all users have 1Mbps and 40ms RTT connections • A/B Testing to find an optimal model • Customized packaging for user groups • Per browser groups: ~5% improvements • Locale / IP Prefix might yield better performance
Human errors are possible 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>
Summary • Performance optimization must be adaptive • Good interface helps optimization • Trace-based analysis is powerful • Always monitor the optimization effect