Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Performance and Maintainability with Continuous...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Seth Walker
April 24, 2014
Technology
1.3k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Performance and Maintainability with Continuous Experimentation
Seth Walker
April 24, 2014
More Decks by Seth Walker
See All by Seth Walker
A Public Commitment to Performance
sethwalker
0
3.7k
Other Decks in Technology
See All in Technology
AI x 開発生産性を取り巻く予算戦略と投資対効果
i35_267
7
3.4k
AI驚き屋発見器
yama3133
1
310
ダッシュボード"開発"について 〜使われるダッシュボードのつくりかた〜
kimichan
0
220
AIコード生成×サプライチェーン攻撃 — PHPが直面する“二重の信頼問題
shinyasaita
0
490
どこまでAIに任せるか 〜確率論と決定論の境界決定〜
shukob
0
520
AI工学特論: MLOps・継続的評価
asei
10
2.6k
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
15
110k
2年前に削除したPHPクラスが、 ある日突然決済をエラーにした
ykagano
1
840
AI Agent を本番環境へ―― Microsoft Foundry × Azure Serverless で作る Enterprise-Ready な基盤
shibayan
PRO
1
500
AI研修(Day1)【MIXI 26新卒技術研修】
mixi_engineers
PRO
1
1.2k
PHPで作って学ぶリアルタイム音声対話AIとWebSocket入門 by ムナカタ
munakata
0
160
歴史から理解するクラウドインフラのしくみ
kizawa2020
0
150
Featured
See All Featured
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
440
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
Claude Code のすすめ
schroneko
67
230k
Mobile First: as difficult as doing things right
swwweet
225
10k
Skip the Path - Find Your Career Trail
mkilby
1
170
Statistics for Hackers
jakevdp
799
230k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
Designing Powerful Visuals for Engaging Learning
tmiket
1
460
Exploring anti-patterns in Rails
aemeredith
3
450
Measuring & Analyzing Core Web Vitals
bluesmoon
9
910
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
180
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
270
Transcript
Performance and Maintainability with Continuous Experimentation @sethwalker sethwalker.me/talks/continuous-experimentation
@sethwalker Seth Walker Allison McKnight Jonathan Klein @sethwalker @aemcknig @jonathanklein
Daniel Espeset @danielespeset @dxna Daniel Na Lara Swanson @laraswanson
None
@sethwalker
@sethwalker 175 committers
@sethwalker 100 committers touch CSS & JS
@sethwalker
@sethwalker Confidence?
Operations
@sethwalker Feature Flags
@sethwalker $cfg['save_everything'] = 'staff'; // ... snip ... if (isEnabled('save_everything'))
{ writeToDB($everything); } else { throwAway($everything); }
@sethwalker $cfg['save_everything'] = '1%'; // ... snip ... if (isEnabled('save_everything'))
{ writeToDB($everything); } else { throwAway($everything); }
@sethwalker $cfg['save_everything'] = '5%'; // ... snip ... if (isEnabled('save_everything'))
{ writeToDB($everything); } else { throwAway($everything); }
@sethwalker $cfg['save_everything'] = '1%'; // ... snip ... if (isEnabled('save_everything'))
{ writeToDB($everything); } else { throwAway($everything); }
@sethwalker $cfg['save_everything'] = '5%'; // ... snip ... if (isEnabled('save_everything'))
{ writeToDB($everything); } else { throwAway($everything); }
@sethwalker $cfg['save_everything'] = '10%'; // ... snip ... if (isEnabled('save_everything'))
{ writeToDB($everything); } else { throwAway($everything); }
@sethwalker $cfg['jquery_1_11'] = 'staff'; // ... snip ... if (isEnabled("jquery_1_11"))
{ <script src="/js/lib/jquery-1.11.0.js"></script> } else { <script src="/js/lib/jquery-1.8.2.js"></script> }
@sethwalker $cfg['jquery_1_11'] = '5%'; // ... snip ... if (isEnabled("jquery_1_11"))
{ <script src="/js/lib/jquery-1.11.0.js"></script> } else { <script src="/js/lib/jquery-1.8.2.js"></script> }
@sethwalker $cfg['jquery_1_11'] = '50%'; // ... snip ... if (isEnabled("jquery_1_11"))
{ <script src="/js/lib/jquery-1.11.0.js"></script> } else { <script src="/js/lib/jquery-1.8.2.js"></script> }
None
None
None
None
None
@sethwalker $cfg['jquery_1_11'] = '5%'; // ... snip ... if (isEnabled("jquery_1_11"))
{ <script src="/js/lib/jquery-1.11.0.js"></script> } else { <script src="/js/lib/jquery-1.8.2.js"></script> }
None
None
None
None
@sethwalker $cfg['jquery_1_11'] = '50%'; // ... snip ... if (isEnabled("jquery_1_11"))
{ <script src="/js/lib/jquery-1.11.0.js"></script> } else { <script src="/js/lib/jquery-1.8.2.js"></script> }
@sethwalker $cfg['jquery_1_11'] = '100%'; // ... snip ... if (isEnabled("jquery_1_11"))
{ <script src="/js/lib/jquery-1.11.0.js"></script> } else { <script src="/js/lib/jquery-1.8.2.js"></script> }
None
@sethwalker
@sethwalker window.Etsy.Context = { // ... snip ... "feature":{ "conversations.rejuvination":true,
"activity.dynamic_load_on_scroll":true, "overlays.buttery_smooth":true, "collections.perf_render_fix":true, } };
@sethwalker if (Etsy.Context.feature["overlays.buttery_smooth"]) { doSmooth(); } else { doJanky(); }
@sethwalker TODO: Feature Flags for the asset pipeline
@sethwalker $cfg['js_debug_build'] = 'staff'; // ... snip ... if (isEnabled("js_debug_build"))
{ <script src="/js-debug/main.js"></script> } else { <script src="/js/main.js"></script> }
@sethwalker + Analytics
Continuous Experimentation
@sethwalker Small, measurable changes Dan McKinley - http://mcfunley.com/design-for-continuous-experimentation
@sethwalker Validate hypotheses
@sethwalker Invalidate hypotheses
None
None
@sethwalker
None
:(
@sethwalker 100+ active flags
@sethwalker 60+ active experiments
@sethwalker 14 experimental iterations on listing page redesign
None
None
None
None
None
None
None
None
None
None
None
None
None
@sethwalker N inactive experiments
@sethwalker N inactive experiments N > 0
@sethwalker Cruft
@sethwalker if (isEnabled("new_listing_page")) { <script src="/js/listing/new-listing.js"></script> } if (isEnabled("new_favorite_button")) {
<script src="/js/new-favorites.js"></script> } if (isEnabled("cart2")) { <script src="/js/add-to-cart2.js"></script> }
@sethwalker $cfg["new_listing_page"] = "100%"; $cfg["new_favorite_button"] = "5%"; $cfg["cart2"] = "50%";
@sethwalker define("foo", ["logger"], function(Logger) { Logger.warn("foo is deprecated!"); doFoo(); });
@sethwalker <link rel="stylesheet" href="/css/base.css" /> <link rel="stylesheet" href="/css/listing.css" /> if
(isEnabled("new_listing_page")) { <link rel="stylesheet" href="/css/new-listing.css" /> } if (isEnabled("new_favorite_button")) { <link rel="stylesheet" href="/css/new-favorites.css" /> } if (isEnabled("cart2")) { <link rel="stylesheet" href="/css/add-to-cart2.css" /> }
@sethwalker Let's clean up!
Fear
@sethwalker Throw away
@sethwalker Throw away ability
@sethwalker Design for Throwaway-ability Bill Scott - http://www.looksgoodworkswell.com/the-experimentation-layer/
@sethwalker Tools
@sethwalker Needs More Visibility
None
None
None
None
None
None
None
@sethwalker selectorText = document.styleSheets[i].cssRules[j].selectorText; selected = document.querySelector(selectorText); results.push({ selector: selectorText,
found: !!selected ? 1 : 0}); // ... snip ... log(results);
@sethwalker Existing code - Seen in the wild = SUSPECT
@sethwalker Instrumentation
@sethwalker Increasing confidence
@sethwalker Adapting tools and process
Thanks! @sethwalker sethwalker.me/talks/continuous-experimentation